我遇到调用promises / functions的顺序问题。基本上我获取一个ID数组,然后,对于每个id,想要获取订单详细信息并保存。然后转到下一个ID。截至目前,在获取每个订单详细信息之前,它不会保存。
代码:
// Convenience function
var fetchOrders = function() {
return self.fetchOrderList()
.then(function(orders) {
return P.map(orders, function(r) {
return self.fetchOrderById(r.id).then(fn);
});
});
};
// Fetch initial order list
var fetchOrderList = function() {
return new P(function(resolve, reject) {
debug('Fetching initial list');
resolve([{
id: 123
}, {
id: 134
}, {
id: 1333
}]);
});
};
var fetchOrderById = function(id) {
return new P(function(resolve, reject) {
debug('Fetching by ID');
resolve({
foo: 'bar'
});
}).then(function(o) {
debug('Saving');
return o;
})
};
fetchOrders();
预期结果:
Fetching initial list
Fetching by ID
Saving
Fetching by ID
Saving
Fetching by ID
Saving
实际结果
Fetching initial list
Fetching by ID
Fetching by ID
Fetching by ID
Saving
Saving
Saving
答案 0 :(得分:1)
好的,我明白为什么它正在做它正在做的事情。首先,我将解释原因,然后讨论可能的变化。
在您的测试代码中,如果没有为P.map()
设置选项,它会一个接一个地同步调用所有fetchOrderById()
操作,这样它们就会同时在飞行中(如果它们是真的异步操作)。
因此,您已经为所有订单启动了ID操作的所有提取。然后,当每个解析后,他们将运行保存。在测试代码中,它们都立即解决。但是,通过Promise规范,所有.then()
处理程序在所有同步代码解除并完成后异步调用(从技术上讲,我认为它使用类似nextTick()
的方式来安排每个.then()
处理程序)。
因此,您会看到所有按ID获取,它们都会同步解析,这会将所有保存操作排入队列以在nextTick上运行。这样就可以得到你看到的实际结果。
如果fetchByOrderId()实际上是异步的(它稍后会解决),你仍会看到所有的提取都会立即开始 - 所有这些请求都将被启动,然后保存会发生,因为id的每次提取都会到达。
如果你真的想把它更改为Fetch by ID / save,Fetch by ID / save,Fetch by ID / save,我可以想出一个很好的方法来构建它,但这必然会对所有操作进行排序并采取措施更长的时间(没有并行的网络运营)。
仅供参考,我将您的代码放入正在运行的jsFiddle中以进行测试:http://jsfiddle.net/jfriend00/k49qbd3z/。我只需删除一个.then(fn)
,因为您提供的代码中没有fn
。
您可以通过将{concurrency: 1}
添加到P.map()
来获取请求的输出,以强制它一次只执行一项操作。
// Convenience function
var fetchOrders = function() {
return fetchOrderList().then(function(orders) {
return P.map(orders, function(r) {
return fetchOrderById(r.id);
}, {concurrency: 1});
});
};
请参阅此处的演示演示:http://jsfiddle.net/jfriend00/wshLu0g5/,输出结果为:
Fetching initial list
Fetching by ID
Saving
Fetching by ID
Saving
Fetching by ID
Saving
请记住,这可能会严重降低最终结果的速度,因为您要按序ID序列化所有提取并一次只保存到一个操作。获取一个id的数据,然后保存,然后获取下一个id的数据,然后保存,然后获取下一个id的数据,然后保存它等等。