[英]How to create a initialization function with promises?
我只需要为模块调用一次的初始化函数。 此函数是一个promise,由execute函数调用。 如果execute被调用两次,则第二个必须等待初始化然后继续执行。
我编写了这段代码,但是execute的第二个调用始终在等待,并且永远不会返回。 我错过了什么?
var initialized = false;
var initializing = false;
var initializationPromise;
var init = function () {
initializing = true;
return q.promise(function (resolve) {
// simulate initialization
setTimeout(function () {
// initialized
initialized = true;
resolve();
}, 1000);
}).fin(function () {
initializing = false;
});
};
var execute = function () {
return q.promise(function (resolve, reject, notify) {
if (initialized) {
// already initialized
resolve();
} else {
if (!initializing) {
// initializing
initializationPromise = init().then(function () {
// simulate execution
setTimeout(function () {
resolve();
}, 1000);
}, function (reason) {
reject(reason);
});
} else {
// Wait : initializing in progress
return initializationPromise;
}
}
});
};
execute().then(function () {
// This is executed
});
execute().then(function () {
// This is never executed
});
// Wait : initializing in progress return initializationPromise;
是不正确的。 那什么也没有等待,它只是退出了q.promise
构造函数,什么也不做。 同样,您似乎也采用了Promise
构造函数antipattern 。
你应该做的是
var initialisationPromise = null;
function isInitialised() {
return initialisationPromise != null && initialisationPromise.isFulfilled();
}
function isInitialising() {
return initialisationPromise != null && initialisationPromise.isPending();
}
function init() {
// init can be called as often as necessary, and returns when it's done
if (initialisationPromise == null) { // do the test here!
// this part runs only once
initialisationPromise = q.promise(function (resolve) {
// simulate initialization
setTimeout(function () {
// initialized
resolve();
}, 1000);
});
}
return initialisationPromise;
}
function execute() {
return init().then(function () {
return q.promise(function(resolve, reject, notify) {
// simulate execution
setTimeout(function () {
resolve();
}, 1000);
});
});
}
已解决/已拒绝的诺言将保持其状态(已解决或已拒绝状态),因此您只能使用它运行一次初始化代码。 为此, init()
函数应始终返回相同的承诺,而不是每次都创建它。
因此,我们在init()
方法外部创建一个延迟对象( initializationDeferred
),并在每次调用init()
方法时使用initializationDeferred
返回相同的promise 。 我们需要,也给检查init()
已经被做过,我们使用的共享变量initializationStarted
跳过setTimeout
如果已经在先前的调用来完成。
现在,在execute
内部,可以确保只有在init()
方法时才调用then()
的onFulfilled回调。
var initializationDeferred = Q.defer(); // Create here the deferred object so it's common to all init() invocations var initializationStarted = false; var init = function() { if (!initializationStarted) { initializationStarted = true; setTimeout(function() { // initialized console.log('Init timeout fired!'); initializationDeferred.resolve(true); // Resolve the promise associated to the deferred object }, 1000); } return initializationDeferred.promise; // Return the promise associated to the deferred object }; var execute = function() { return init().then(function(initialized) { // Here your module is initialized and you can do whatever you want // The value of "initialized" here is always "true" console.log('Execute: initialized?', initialized); }); }; execute().then(function() { // This is executed console.log('Execute First invocation'); }); execute().then(function() { // This is executed too console.log('Execute Second invocation'); });
<script src="http://cdnjs.cloudflare.com/ajax/libs/q.js/0.9.2/q.js"></script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.