Javascript 如何链接同步函数以异步运行?
我认为董事会还没有讨论过这个问题。我一直在研究承诺链,我发现你可以将承诺链到特定的延迟者。这允许通过then语句注册的所有函数从我读到的内容异步调用。但是,这假设这些函数是异步编写的。例如,如果我有以下几点:Javascript 如何链接同步函数以异步运行?,javascript,jquery,node.js,asynchronous,Javascript,Jquery,Node.js,Asynchronous,我认为董事会还没有讨论过这个问题。我一直在研究承诺链,我发现你可以将承诺链到特定的延迟者。这允许通过then语句注册的所有函数从我读到的内容异步调用。但是,这假设这些函数是异步编写的。例如,如果我有以下几点: 函数asyncEvent(){ var dfd=jQuery.Deferred(); dfd.决议(“启动”); 返回dfd.promise(); } $.when(asyncEvent())。然后( 功能(状态){ 控制台日志(状态); setTimeout(function(){co
函数asyncEvent(){
var dfd=jQuery.Deferred();
dfd.决议(“启动”);
返回dfd.promise();
}
$.when(asyncEvent())。然后(
功能(状态){
控制台日志(状态);
setTimeout(function(){console.log(“1”);},1000);
}
).然后(功能(状态){
setTimeout(function(){console.log(“2”);},1000);
});代码>
如何链接同步函数以与异步运行
承诺
但是,我的问题是,这一承诺是否可以在未来几年内含蓄地改变
然后是语句,还是必须使用如下代码(即
我能想到的唯一办法是什么
注意,当
然后,函数中的函数返回。我想避免这种情况,如果
可能
如果要求链接同步函数,请尝试使用.queue()
或$.queue()
.queue()
允许链接.promise(“queueName”)
,其中可以在调用所有`“queueName”函数时对“queueName”
jQuery promise对象调用()
var fns=[
函数异步事件(下一个){
var msg=“开始”;
//将'msg'推送到'this.status'数组
this.status.push(msg);
控制台日志(msg);
//在队列中调用'next'函数
next();
},
功能(下一个){
var msg=“1”;
setTimeout(函数(){
//将'msg'推送到'this.status'数组
this.status.push(msg);
控制台日志(msg);
//在队列中调用'next'函数
下一个()
}.绑定(本),1000);
},
功能(下一个){
var msg=“2”;
setTimeout(函数(){
//将'msg'推送到'this.status'数组
this.status.push(msg);
控制台日志(msg);
//在队列中调用'next'函数
下一个()
}.绑定(本),1000);
}
]
,obj={
地位:[]
};
//设置`“queueName`,调用`.queue()`并将函数数组`fns`作为参数
$(obj).队列(“状态”,fns)
.退出队列(“状态”)
//在调用所有`“queueName``函数时执行这些操作
.承诺(“地位”)
.然后(函数(){
console.log(“完成”,此[0]。状态)
});代码>
您不应该访问返回的承诺。然后
但是,正如您已经看到的,您可以在此中创建一个新承诺。然后
并在下一个中附加回调。然后
在解决此新承诺后执行,我在所附stackoverflow帖子中的实现中看到,承诺总是由另一个名为“延迟”的实体来解决,实际上您不需要创建延迟实例,因为承诺可以自行解决,如果您查看了的文档,您将看到构造函数收到一个用于解析/拒绝承诺本身的执行器函数,因此您可以使用以下内容:
new Promise(function (resolve, reject) {
// do something async and then reject/resolve itself
setTimeout(function () {
resolve()
}, 1000)
})
您的示例可以使用此构造函数编写,如下所示:
new Promise(function (resolve) {
resolve('start')
})
.then(function (status) {
return new Promise(function (resolve, reject) {
console.log(status)
// do something async and then reject/resolve itself
setTimeout(function () {
console.log(1)
resolve()
}, 1000)
})
})
.then(function () {
setTimeout(function () {
console.log(2)
}, 1000)
})
需要记住的是,您不能更改承诺履行/拒绝后的状态,如果您希望基于的内容链接函数,请确保返回承诺,这样,如果有,则在原始承诺中附加了,则在。然后
得到满足/拒绝
仅供参考,以上是以下方面的快捷方式:
new Promise (function (resolve) {
resolve('start')
})
.then(function (status) {
return new Promise (function (resolve, reject) {
console.log(status)
setTimeout(function () {
console.log(1)
resolve()
}, 1000)
})
.then(function () {
setTimeout(function () {
console.log(2)
}, 1000)
})
})
也许这就是你想要的
function asyncEvent() {
var dfd = jQuery.Deferred();
setTimeout(function () {
console.log('start');
dfd.resolve("start");
}, 1000)
return dfd.promise();
}
var chainSyncOrAsync = function (outerDef) {
var toReturn = {};
toReturn.chain = function (defOrFunction) {
// console.log(outerDef, defOrFunction, '---');
var def = defOrFunction, toExecute = false;
if (typeof def === 'function') {
toExecute = true;
def = jQuery.Deferred();
}
outerDef.then(function () {
// console.log(toExecute, defOrFunction);
if (toExecute) {
var result = defOrFunction();
if (result) {
result.then(function () {
def.resolve();
})
} else {
def.resolve(result)
}
}
})
return chainSyncOrAsync(def);
}
return toReturn;
}
chainSyncOrAsync(asyncEvent())
.chain(function () {
console.log(1)
})
.chain(function () {
console.log(2)
})
.chain(function () {
return asyncEvent();
})
.chain(function () {
console.log(3)
})
.chain(function () {
console.log(4)
})
因此,在查看源代码之后,我认为我不能使用队列,因为使用承诺的全部原因是为了避免无限的堆栈帧扩展。这些队列绕过它的唯一方法是,它们调用setTimeout,这是在堆栈帧从我的理解中清除后触发的。因此,如果在fns中编写异步代码,它将在每次调用时扩展堆栈。除了承诺型架构之外,还有其他解决方法吗?@fritz不确定是否正确解释了这个问题?“但是,我的问题是,在then语句中是否可以隐式更改承诺,或者您是否必须使用以下代码(这是我唯一可以想到的方法)?”预期的结果是什么?承诺不能“含蓄地改变”.then()
返回jQuery版本1.8+上的新jQuery承诺对象。使用setTimeout
不会隐式返回值或承诺。需要创建新的延迟对象以在setTimeout
之后返回值,或者使用.delay()
,.promise()
将jQuery对象返回到链接的。然后()
我对误解表示道歉,我应该更清楚。当我说“隐式更改”时,我的意思是为每个.then()
生成一个新的承诺/延期,然后独立于原始承诺进行解析。因此,与链接.then()
“不同的是,允许链接不能一次解决的承诺s@fritz“为每个.then()生成一个新的承诺/延迟者,然后将其独立于原始承诺之外解析”一个新的$。延迟的或jQuery承诺对象需要从中返回。then()
,例如,d
在第一个中。然后()
在$之后。当(asyncEvent())
我不确定,但我只是运行了此代码,超时大致同时触发,而不是按顺序触发。我相信您在调用defOrFunction()时出错。如果函数不返回resol,则会进入竞争状态