从嵌套的异步函数调用返回谓词

时间:2014-03-23 15:10:41

标签: javascript node.js asynchronous underscore.js predicate

我需要过滤一个数组,具体取决于通过从外部API检索数据获得的每个元素的子元素是否与标准匹配。

代码可能比解释更清晰:

//Suppose there is an array filled
//_.filter(array, predicate)
var filtered_array = _.filter(array,function(element){
   //Async operation
   webservices.doStuff(element, function(sub_element){
        //This return is meant for the filter, but returns on .doStuff callback
       return sub_element.thing === "ok";
   });
});

这里的问题是,我不知道如何在这里返回谓词的结果,因为webservices.doStuff是异步的!

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

您应该查看async.js库https://github.com/caolan/async,它可以执行大量异步请求,并在完成所有请求后发出一个回调,并为您提供所有结果的列表,然后,您可以应用过滤功能。我不记得你,你可以立即提供一个谓词函数来描述应该在最终结果集中的哪些结果,但是如果库不支持它,它应该能够做这样的事情而不需要太多的工作。

查看async.js文档中的过滤器函数。

答案 1 :(得分:0)

我会使用Q或async来执行此操作。请考虑以下示例,将每个Web服务调用包装在一个promise中,并定义在解决所有promise时将解析的另一个promise。然后根据您的逻辑过滤结果(即所有调用的所有返回的数组)。

 var source = [{a : 1}, {a:2}...] // your data

 var all = Q.all(source.map((o) => Q.Promise((resolve, reject,notify) 
                   => webService.doStuff(o, resolve, reject))))

 all.then((ret) => _.filter(ret.data, (elem) => elem.thing === "ok"))
    .then((filtered) => ... // do something with filtered )

您的网络服务代理很可能已经与Q或其他承诺库绑定。所以你的代码会变得更简单,比如:

var all = Q.all(source.map(webService.doStuff))
           .then(filter).then(process)

或者至少你可以将它重构为那么简单。

总体而言,由于node.js环境的非阻塞 - 接受 - 回调和转换性质,掌握一个或多个承诺库是必不可少的,asyncQ是最受欢迎的两个据我所知。

更新:现在它似乎是蓝鸟,它也是最快的。)

使用其中任何一个都可以让你在处理异步调用时提出更简单的设计。