如何根据异步调用的返回值做出决策?

时间:2017-01-05 20:38:20

标签: ajax node.js http promise

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调用是异步的,所以出错了,循环永远不会结束。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

您可以使用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

答案 1 :(得分:0)

您不能使用等待异步结果的同步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
});