简体   繁体   English

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

[英]Return predicate from nested async function call

I need to filter an array, depending whether or not each element's sub-element, obtained by retrieving data from an external API, matches a criteria. 我需要过滤一个数组,具体取决于通过从外部API检索数据获得的每个元素的子元素是否与条件匹配。

The code might be clearer than an explanation : 该代码可能比解释更清楚:

//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";
   });
});

The problem here, is I don't know how to return the predicate's result here, as webservices.doStuff is asynchronous! 这里的问题是,我不知道如何在这里返回谓词的结果,因为webservices.doStuff是异步的!

Any idea? 任何想法?

You should take a look in the async.js library https://github.com/caolan/async which can do alot of async requests, and issue a single callback when all the request are done, and provide you with a list of all the results, which you then can apply you filter function on. 您应该看一下async.js库https://github.com/caolan/async ,它可以执行许多异步请求,并在所有请求完成后发出一个回调,并为您提供所有列表结果,然后可以将其应用到过滤器功能上。 I cannot remember you you can provide a predicate function right away describe which results that should be in the final resultset, but it should be do able to do such a thing, without too much work, if the library doesn't already support it. 我不记得您可以立即提供谓词函数来描述应该在最终结果集中的结果,但是如果库尚不支持,则无需过多的工作即可完成这样的事情。

Take a look at the filter function in the async.js documentation. 看一下async.js文档中的filter函数。

I would use Q or async to do this. 我会用Q或异步来做到这一点。 Consider following example, you wrap each web service call in a promise and define another promise that will be resolved when all promises are resolved. 考虑下面的示例,您将每个Web服务调用包装在一个Promise中,并定义在所有Promise都解决后将要解决的另一个Promise。 Then you filter results ( ie array of all returns from all calls) according to your logic. 然后根据逻辑过滤结果(即所有调用的所有返回的数组)。

 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 )

Most likely your web service proxy already have binding with Q or another promise library. 您的Web服务代理很可能已经与Q或另一个Promise库绑定。 So your code is going to be simpler, something like: 因此,您的代码将变得更加简单,例如:

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

Or at least you can refactor it to be that simple. 或者至少您可以将其重构为如此简单。

Overall due to non-blocking-accept-callback-and-go nature of node.js environment, it is essential to master one promise library or another, async and Q are two most popular to the best of my knowledge. 总体而言,由于node.js环境的非阻塞性,接受和执行性质,掌握一个或另一个承诺库至关重要,据我所知, asyncQ是最受欢迎的两个。

( Update : right now it seems to be bluebird, and it is fastest too.) 更新 :现在它似乎是蓝鸟,而且它也是最快的。)

Having either of them allow you to come up with much easier design when dealing with async calls. 拥有它们中的任何一个都可以使您在处理异步调用时提出更简单的设计。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM