由于低版本Qt不支援JavaScript的Promise對象,是以這裡用一個輕量級Promise的例子列舉一下。
原版代碼路徑:https://github.com/stackp/promisejs
這裡我們進行了一下裁剪,去除網絡請求的部分,新的代碼如下:
// promise.js
(function(exports) {
function Promise() {
this._callbacks = [];
}
Promise.prototype.then = function(func, context) {
var p;
if (this._isdone) {
p = func.apply(context, this.result);
} else {
p = new Promise();
this._callbacks.push(function () {
var res = func.apply(context, arguments);
if (res && typeof res.then === 'function')
res.then(p.done, p);
});
}
return p;
};
Promise.prototype.done = function() {
this.result = arguments;
this._isdone = true;
for (var i = 0; i < this._callbacks.length; i++) {
this._callbacks[i].apply(null, arguments);
}
this._callbacks = [];
};
function join(promises) {
var p = new Promise();
var results = [];
if (!promises || !promises.length) {
p.done(results);
return p;
}
var numdone = 0;
var total = promises.length;
function notifier(i) {
return function() {
numdone += 1;
results[i] = Array.prototype.slice.call(arguments);
if (numdone === total) {
p.done(results);
}
};
}
for (var i = 0; i < total; i++) {
promises[i].then(notifier(i));
}
return p;
}
function chain(funcs, args) {
var p = new Promise();
if (funcs.length === 0) {
p.done.apply(p, args);
} else {
funcs[0].apply(null, args).then(function() {
funcs.splice(0, 1);
chain(funcs, arguments).then(function() {
p.done.apply(p, arguments);
});
});
}
return p;
}
var promise = {
Promise: Promise,
join: join,
chain: chain
};
exports.promise = promise;
})(this);
// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QFile>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
QString fileName = ":/promise.js";
QFile jsFile(fileName);
if (!jsFile.open(QIODevice::ReadOnly))
return -1;
QString contents = jsFile.readAll();
jsFile.close();
engine.evaluate(contents, fileName);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
// main.qml
import QtQuick 2.6
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
function late(n) {
var p = new promise.Promise();
p.done(n, null);
return p;
}
Component.onCompleted: {
late(100)
.then(
function(n, err) {
console.log(n);
return late(n + 200);
})
.then(
function(n, err) {
console.log(n);
return late(n + 300);
})
.then(
function(n, err) {
console.log(n);
return late(n + 400);
})
.then(
function(n, err) {
console.log(n);
});
}
}