Javascript 如何链接同步函数以异步运行?

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

我认为董事会还没有讨论过这个问题。我一直在研究承诺链,我发现你可以将承诺链到特定的延迟者。这允许通过then语句注册的所有函数从我读到的内容异步调用。但是,这假设这些函数是异步编写的。例如,如果我有以下几点:

函数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,则会进入竞争状态