【问题标题】:How to make decisions based on return value of async calls?如何根据异步调用的返回值做出决策?
【发布时间】:2017-01-06 09:19:10
【问题描述】:

Node.js

while(list != []) {
  apiCall.then(function(data){
    list = data;
  });

}

其中 apiCall 是一个类似如下构造的承诺:

return new Promise(function (fulfill, reject){
        request("url", function (error, response, body){
            try {
                fulfill(body);
            } catch (error) {
                reject(error);
            }
        }, reject);
    }); 

因为 api 调用是异步的,所以会出现问题并且循环永远不会结束。我该如何解决这个问题?

【问题讨论】:

  • 使用已为您提供的回调。

标签: ajax node.js http promise


【解决方案1】:

您不能使用同步 while 循环来等待异步结果。异步回调,在这种情况下,.then() 处理程序将永远不会执行。您不能以这种方式编写单线程 Javascript。解释器只会永远运行您的 while 循环,尽管事件可能会堆积在事件队列中以触发异步回调,但这些事件永远不会得到服务,因为您的 while 循环永远不会停止。在像 Javascript 这样的事件驱动的单线程环境中,您不能以这种方式对异步行为进行编程。

相反,您不需要使用同步循环。典型的解决方案包括进行异步调用,评估结果。如果你想在那个时候再次执行异步函数,你可以调用一个函数来再次执行它。

function runIt() {
     return a().then(function() {
         if (needToRunAgain) {
             return runIt();
         } else {
             return someValue;
         }
     });
}

如果条件需要,这将再次调用异步操作,并将生成的 Promise 链接到原始 Promise,让调用者准确知道结果何时最终完成。然后你像这样调用代码:

runIt(...).then(function(result) {
    // result here
    // you must use the async result here or call a function and pass the result
    // to it.  You cannot assign it to a higher scoped variable and expect 
    // other code that follows to be able to use it.
}, function(err) {
    error here
});

【讨论】:

    【解决方案2】:

    您可以使用SynJS 在循环内同步运行带有回调的函数。这是一个工作代码来说明:

    var SynJS = require('synjs');
    var request = require('request');
    
    function myFunction1(modules) {
        var list, i=0;
        while(i<5) {
            modules.request("http://www.google.com", function (error, response, body){
                list = body;
                console.log("got it!", i, new Date());
                modules.SynJS.resume(_synjsContext); //<-- indicates that callback is finished
            });
            SynJS.wait(); //<-- wait for callback to finish
            i++;
        };
    };
    
    var modules = {
            SynJS:  SynJS,
            request:    request,
    };
    
    SynJS.run(myFunction1,null,modules,function (ret) {
        console.log('done');
    });
    

    这是一个结果:

    got it! 0 Thu Jan 05 2017 18:17:20 GMT-0700 (Mountain Standard Time)
    got it! 1 Thu Jan 05 2017 18:17:20 GMT-0700 (Mountain Standard Time)
    got it! 2 Thu Jan 05 2017 18:17:21 GMT-0700 (Mountain Standard Time)
    got it! 3 Thu Jan 05 2017 18:17:21 GMT-0700 (Mountain Standard Time)
    got it! 4 Thu Jan 05 2017 18:17:21 GMT-0700 (Mountain Standard Time)
    done
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-16
      • 2012-03-13
      • 2021-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-13
      • 2013-02-14
      相关资源
      最近更新 更多