简体   繁体   English

for循环内的异步函数调用

[英]Asynchronous function call inside for loop

I am having a problem trying to make my for loop behave synchronously when I am making an asynchronous call in each iteration of the loop. 我在循环的每个迭代中进行异步调用时都试图使我的for循环行为同步时遇到问题。

Here is my code: 这是我的代码:

pipeline: function(userContext, options, done){

    var orderData = [];

    options.data.forEach(function(store, index){
        store.orders.forEach(function(order){
            shopify.getPipeline(userContext, {'order':order,'storeId':index}, function(result){
                var snapshotId = "30775bf1bb854c5d84c9c2af37bc8fb0";
                var resourceToQuery = config.structrUrls.getUrl("ConfigurationSnapshot") + '/' + snapshotId ;
                var requestOptions = {
                    method: "GET",
                    timeout: 8000
                };
                requestify.request(resourceToQuery, requestOptions)
                    .then(function(snapshotResult){
                        result.snapshots = snapshotResult.getBody().result;
                        result.snapshots.configurationPayload = JSON.parse(snapshotResult.getBody().result.configurationPayload);
                        orderData.push(result);
                    })
                    .catch(function(err){
                        console.log (err);
                        done(err);
                    });
            });
        });
    });

    done(null, orderData);

}

I understand the problem here, but do not know how to remedy it. 我在这里了解问题,但不知道如何解决。 Let me explain the function: 让我解释一下功能:

options.data contains an array of stores, and each store contains an array of orders. options.data包含一个存储数组,每个存储包含一个订单数组。 For each order, I am calling shopify.getPipeline() for pipeline data (this is a synchronous operation), and in the callback I make a requestify request (a node module used for making http requests) for snapshot data, which I want to append to the result before pushing it onto my "orderData" array. 对于每个订单,我正在调用shopify.getPipeline()来获取管道数据(这是一个同步操作),并且在回调中我向快照数据发出一个requestify请求(用于发出http请求的节点模块),我想将结果追加到我的“ orderData”数组之前。 When this all completes, I am calling "done", a callback function, with my orderData. 所有这些完成后,我将使用orderData调用回调函数“ done”。 As you can see, since requestify calls are asynchronous, done is called before any data is added to the orderData array. 如您所见,由于requestify调用是异步的,因此在将任何数据添加到orderData数组之前将调用done。

I think I need to use some kind of promise in order to guarantee the result before calling done, but I have been unsuccessful in implementing a promise into this function. 我认为我需要使用某种promise才能在调用完成之前保证结果,但是在将promise实现到此函数中我一直没有成功。 In the documentation for q , it seems like the function I would want to use is promise.all(), which 'Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected'. q的文档中,似乎我要使用的函数是promise.all(),该函数“返回一个诺言,该诺言通过包含每个诺言的实现值的数组来实现,或者由于相同的拒绝原因而被拒绝作为被拒绝的第一个诺言”。 I'm failing to see how to translate my forEach loop into an array of promises. 我没有看到如何将我的forEach循环转换成一个Promise数组。 I was also looking at the async parallel function and ran into the same problem regarding the array of functions. 我也在看异步并行函数,并在函数数组方面遇到了同样的问题。

Any help is greatly appreciated. 任何帮助是极大的赞赏。 Thanks! 谢谢!

To construct an array of Promises for use in Promise.all , you can map across the array of stores, and again across the array of orders, returning a Promise for each order which will be resolved or rejected based on the result of requestify.request . 要构建Promise.all使用的Promises数组,您可以在商店的整个数组中进行map ,并在订单的整个数组中进行map ,为每个订单返回Promise,将根据requestify.request的结果来解决或拒绝该订单。 Merging the resulting nested array gives you a single array of promises which can then be passed to Promise.all . 合并生成的嵌套数组将为您提供一个promise数组,然后将其传递给Promise.all

Using your example: 使用您的示例:

pipeline: function(userContext, options, done){
    var nestedPromises = options.data.map.forEach(function(store, index){
        return store.orders.map(function(order){
            return new Promise(function(resolve, reject){
                shopify.getPipeline(userContext, {'order':order,'storeId':index}, function(result){
                    var snapshotId = "30775bf1bb854c5d84c9c2af37bc8fb0";
                    var resourceToQuery = config.structrUrls.getUrl("ConfigurationSnapshot") + '/' + snapshotId ;
                    var requestOptions = {
                        method: "GET",
                        timeout: 8000
                    };
                    requestify.request(resourceToQuery, requestOptions)
                        .then(function(snapshotResult){
                            result.snapshots = snapshotResult.getBody().result;
                            result.snapshots.configurationPayload = JSON.parse(snapshotResult.getBody().result.configurationPayload);
                            resolve(result);
                        })
                        .catch(function(err){
                            reject(err);
                        });
                });
            });
        });
    });
    // Flatten nested array.
    var promises = Array.prototype.concat.apply([], nestedPromises);
    Promise.all(promises).then(function(orderData){
        done(null, orderData);
    }).catch(function(err){
        done(err);
    });
}

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

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