【问题标题】:meteor - Synchronizing multiple async queries before returning?流星 - 在返回之前同步多个异步查询?
【发布时间】:2014-09-19 19:07:56
【问题描述】:

所以我有一个 Meteor 方法,它应该告诉服务器向 3rd 方 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;
    }
});

此同步代码有效。但是,我还没有找到一种使 API 请求异步的好方法。我能找到的最接近解决方案的方法是重新定义方法以仅返回一个 API 请求的结果,然后让客户端循环通过每个 API 链接并为每个链接调用方法。但是,有没有办法将所有这些请求封装到一个很好的方法中,该方法仅在所有 API 请求完成时才返回

【问题讨论】:

    标签: javascript asynchronous meteor


    【解决方案1】:

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

    我做了一个简单的例子,使用setTimeouts来模拟HTTP请求,让你理解原理,我建议你从这段代码开始,用你的HTTP get请求替换虚拟的setTimeout

    该示例是一个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;
        }
    });
    

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

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

    // 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 ]
    

    HTTP.get 异步版本在 Meteor 文档中有详细说明:

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

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

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

    【讨论】:

    • Meteor 有一个很酷的期货抽象:Meteor._wrapAsync,尽量避免样板
    • Meteor.wrapAsync 在您想将异步任务转换为连续的过程同步调用时很有用,但这在这里没有帮助,因为我们想要实现的是同时启动几个我们想要执行的异步任务平行线。另外,使用Meteor.wrapAsync 包装HTTP.get 是没有意义的,因为当您不传递任何回调作为参数时,它已经公开了一个可用的同步版本。
    猜你喜欢
    • 2014-07-20
    • 1970-01-01
    • 2016-02-22
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    • 1970-01-01
    相关资源
    最近更新 更多