在for循环中调用asynchronous函数

我有一个问题试图让我的循环行为同步,当我在循环的每个迭代进行asynchronous调用。

这是我的代码:

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

我理解这里的问题,但不知道如何补救。 让我解释一下这个函数:

options.data包含一系列商店,每个商店都包含一系列订单。 对于每个订单,我调用了shopify.getPipeline()作为pipe道数据(这是一个同步操作),并且在callback函数中为快照数据做了一个请求请求(一个用于发出http请求的节点模块),我想在把它推到我的“orderData”数组之前追加结果。 当这一切完成后,我用我的订单数据调用“完成”,一个callback函数。 正如你所看到的,由于requestify调用是asynchronous的,因此在将任何数据添加到orderData数组之前调用done。

我想我需要使用某种承诺才能在调用完成之前保证结果,但是我一直没有成功实现这个function的承诺。 在q的文档中,似乎我想要使用的函数是promise.all(),它返回一个包含每个promise的履行价值的数组,或者被拒绝的拒绝原因作为第一个被拒绝的承诺“。 我没有看到如何将我的forEach循环转换成承诺数组。 我也在寻找asynchronous并行函数,并遇到了关于函数数组的相同问题。

任何帮助是极大的赞赏。 谢谢!

要构造一个用于Promise.all的Promises数组,您可以map整个商店数组,然后再Promise.all一系列的订单,根据requestify.request的结果为每个订单返回将被parsing或拒绝的Promise 。 合并产生的嵌套数组给你一个承诺的数组,然后可以传递给Promise.all

用你的例子:

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