meteor - 在返回之前同步多个异步查询?

pec*_*eco 9 javascript asynchronous meteor

所以我有一个Meteor方法,它应该告诉服务器向第三方API发送多个API请求,然后将这些查询的结果合并到一个数组中,然后返回给客户端.

但是,在返回结果之前,我似乎找不到服务器等待所有API查询完成的方法.

代码的同步版本只是一个接一个地获取数据API调用,如下所示:

Meteor.methods({
    fetchData: function(APILinks) {
        var data = [];
        APILinks.forEach(function(APILink) {
            var items = HTTP.get(APILink).content.items;
            items.forEach(function (item) {
                data.push(item);
            });
        });
        return items;
    }
});
Run Code Online (Sandbox Code Playgroud)

这个同步代码有效.但是,我无法找到使API请求异步的好方法.我能找到最接近解决方案的方法是重新定义方法以返回仅一个API请求的结果,然后让客户端循环遍历每个API链接并为每个API链接调用方法.但是,有没有办法将所有这些请求包装成一个很好的方法,只有在所有API请求完成后才返回?

sai*_*unt 12

您必须使用异步版本HTTP.get并使用Futures 收集结果.

setTimeout编写了一个使用s模拟HTTP请求的简单示例,以便您了解原理,我建议您从此代码开始,并setTimeout使用您的HTTP get请求替换dummy .

该示例是一个test服务器方法,它将许多任务(n)作为参数,然后启动n个任务,每个任务以索引秒计算其索引的平方.

// we use fibers which is a dependency of Meteor anyway
var Future = Npm.require("fibers/future");

Meteor.methods({
    test: function(n) {
        // build a range of tasks from 0 to n-1
        var range = _.range(n);
        // iterate sequentially over the range to launch tasks
        var futures = _.map(range, function(index) {
            var future = new Future();
            console.log("launching task", index);
            // simulate an asynchronous HTTP request using a setTimeout
            Meteor.setTimeout(function() {
                // sometime in the future, return the square of the task index
                future.return(index * index);
            }, index * 1000);
            // accumulate asynchronously parallel tasks
            return future;
        });
        // iterate sequentially over the tasks to resolve them
        var results = _.map(futures, function(future, index) {
            // waiting until the future has return
            var result = future.wait();
            console.log("result from task", index, "is", result);
            // accumulate results
            return result;
        });
        //
        console.log(results);
        return results;
    }
});
Run Code Online (Sandbox Code Playgroud)

键入> Meteor.call("test",3,function(error,result){console.log(result);});您的浏览器控制台.这将[0,1,4]在3秒后输出.

在您的服务器控制台中,这将输出:

// immediately :
launching task 0
launching task 1
launching task 2
// after 1 second :
result from task 0 is 0
// after 2 seconds :
result from task 1 is 1
// after 3 seconds :
result from task 2 is 4
[ 0, 1, 4 ]
Run Code Online (Sandbox Code Playgroud)

HTTP.get异步版本流星文档详细介绍:

http://docs.meteor.com/#http_call

如果您想更好地了解整个Future概念,请参阅光纤文档:

https://github.com/laverdet/node-fibers

  • 当你想要将异步任务转换为连续的过程同步调用时,`Meteor.wrapAsync`非常有用,但它在这里不会有用,因为我们想要实现的是同时启动我们想要并行执行的几个异步任务.另外,使用`Meteor.wrapAsync`来包装`HTTP.get`是没有意义的,因为当你没有传递任何回调作为参数时,它已经暴露了可用的同步版本. (4认同)