Javascript 如何创建带有承诺的初始化函数?
我需要一个初始化函数,一个模块只调用一次。此函数是一个承诺,由执行函数调用。如果两次调用execute,则第二个必须等待初始化,然后继续执行 我写了这段代码,但是第二次调用execute总是在等待,并且永远不会返回。我错过了什么Javascript 如何创建带有承诺的初始化函数?,javascript,promise,q,Javascript,Promise,Q,我需要一个初始化函数,一个模块只调用一次。此函数是一个承诺,由执行函数调用。如果两次调用execute,则第二个必须等待初始化,然后继续执行 我写了这段代码,但是第二次调用execute总是在等待,并且永远不会返回。我错过了什么 var initialized = false; var initializing = false; var initializationPromise; var init = function () { initializing = true; re
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
});
这是不对的。这并不等待任何事情,它只是从q.promise
构造函数中退出,不做任何事情。此外,你似乎还雇佣了一名员工
你应该做的是
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);
});
});
}
这是不对的。这并不等待任何事情,它只是从q.promise
构造函数中退出,不做任何事情。此外,你似乎还雇佣了一名员工
你应该做的是
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()
函数应该返回始终相同的承诺,而不是每次都创建它
因此,我们在initializationDeferred
方法之外创建一个延迟对象(initializationDeferred
),并使用initializationDeferred
在每次调用init()
方法时返回相同的承诺。我们还需要检查init()
之前是否已经执行过,如果在以前的调用中已经执行过,则使用共享变量initializationStarted
跳过setTimeout
现在,在execute
中,您可以确保只有在初始化init()
方法时才会调用then()
的oncompleted回调
var initializationDeferred=Q.defer();//在这里创建延迟对象,以便它对所有init()调用都是通用的
var initializationStarted=false;
var init=函数(){
如果(!initializationStarted){
initializationStarted=true;
setTimeout(函数(){
//初始化
log('Init timeout fired!');
initializationDeferred.resolve(true);//解析与延迟对象关联的承诺
}, 1000);
}
return initializationDeferred.promise;//返回与延迟对象关联的承诺
};
var execute=function(){
返回init()。然后(函数(已初始化){
//在这里,您的模块被初始化,您可以做任何您想做的事情
//此处“initialized”的值始终为“true”
log('Execute:initialized?',initialized);
});
};
execute().then(function()){
//这是执行
log('executefirst invocation');
});
execute().then(function()){
//这也被执行了
log('executesecondinvocation');
});代码>
已解决/已拒绝的承诺将保持其状态(已解决或已拒绝的状态),因此您只能使用它运行一次初始化代码。为此,init()
函数应该返回始终相同的承诺,而不是每次都创建它
因此,我们在initializationDeferred
方法之外创建一个延迟对象(initializationDeferred
),并使用initializationDeferred
在每次调用init()
方法时返回相同的承诺。我们还需要检查init()
之前是否已经执行过,如果在以前的调用中已经执行过,则使用共享变量initializationStarted
跳过setTimeout
现在,在execute
中,您可以确保只有在初始化init()
方法时才会调用then()
的oncompleted回调
var initializationDeferred=Q.defer();//在这里创建延迟对象,以便它对所有init()调用都是通用的
var initializationStarted=false;
var init=函数(){
如果(!initializationStarted){
initializationStarted=true;
setTimeout(函数(){
//初始化
log('Init timeout fired!');
initializationDeferred.resolve(true);//解析与延迟对象关联的承诺
}, 1000);
}
return initializationDeferred.promise;//返回与延迟对象关联的承诺
};
var execute=function(){
返回init()。然后(函数(已初始化){
//在这里,您的模块被初始化,您可以做任何您想做的事情
//此处“initialized”的值始终为“true”
log('Execute:initialized?',initialized);
});
};
execute().then(function()){
//这是执行
log('executefirst invocation');
});
execute().then(function()){
//这也被执行了
log('executesecondinvocation');
});代码>
通过“此函数是一个承诺”您的意思是“此函数返回一个承诺”?通过“此函数是一个承诺”您的意思是“此函数返回一个承诺”?不,这将运行初始化两次我已更新了代码。检查控制台消息,您将看到初始化代码只执行了一次。是的,initializationStarted
已丢失,感谢您的编辑。否,这将运行初始化两次我已更新代码。检查控制台消息,您将看到初始化代码只执行了一次。是的,initializationStarted
已丢失,感谢您的编辑。我们在逻辑中使用的IsInitialized
和IsInitialized
在哪里?@Ultrablendz我们没有,但似乎OP对它们有一些用处。如果不需要状态,您可以安全地忽略它们。我们在逻辑中使用IsInitialized
和IsInitialized
的位置在哪里?@Ultrablendz我们没有,但OP似乎对它们有一些用处。如果不需要状态,可以安全地忽略它们。