序贯的承诺 [英] Sequential call of promises

查看:43
本文介绍了序贯的承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对诺言/功能的调用顺序有疑问.基本上,我获取一个ID数组,然后对于每个ID,想要获取订单明细并保存.然后转到下一个ID.截至目前,只有在提取了每个订单详细信息后,它才能保存.

I am having an issue with the order in which promises/functions get called. Basically I fetch an array of ID and then, for each id, want to fetch order detail and save. Then on to the next ID. As of now it will not save until every single order detail has been fetched.

代码:

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

推荐答案

好的,我知道它为什么这样做.首先,我将解释原因,然后讨论可能的更改.

OK, I understand why it is doing what it is doing. First, I'll explain why, then discuss possible changes.

在您的测试代码中,并且没有为P.map()设置任何选项,它将逐个同步调用所有fetchOrderById()操作,因此它们将同时处于运行状态(如果它们是真正的异步操作).

In your test code and with no options set for P.map(), it will synchronously call all the fetchOrderById() operations one after another so they would all be in flight at the same time (if they were real async operations).

因此,您已经启动了所有订单的所有ID获取操作.然后,随着这些解析中的每个解析,他们将运行保存.在测试代​​码中,它们都会立即解决.但是,根据Promise规范,所有同步代码都已解绕并完成后,所有.then()处理程序都将被异步调用(从技术上讲,我认为它使用诸如nextTick()之类的东西来调度每个.then()处理程序).

So, you've launched all the fetch by ID operations for all the orders. Then, as each one of those resolves, they will then run the save. In the test code, they all resolve immediately. But, by Promise specification all .then() handlers are called asynchronously AFTER all synchronous code has unwound and finished (technically, I think it uses something like nextTick() to schedule each .then() handler).

因此,您看到所有通过ID进行的获取都发生了,它们都得到了同步解析,这使所有保存操作排队等待在nextTick上运行.这样您就可以看到实际的结果.

So, you see all the fetching by ID happen, they all get resolved synchronously, which queues all the save operations to run at nextTick. Thus you get the actual results you see.

如果fetchByOrderId()实际上是异步的(稍后解决了),您仍然会立即看到所有获取操作-所有这些请求都会启动,然后在每次按id进行获取时都会进行保存.

If the fetchByOrderId() was actually asynchronous (it resolved a bit later), you will still see all the fetches start right away - all those requests would be launched and then saving would happen as each fetch by id arrived.

如果您真的想将其更改为按ID/保存获取",按ID/保存获取",按ID/保存获取",则可以想到一种构造该结构的好方法,但这必然会对所有操作进行排序并采用完成时间更长(无并行网络操作).

If you really want to change it to Fetch by ID/save, Fetch by ID/save, Fetch by ID/save, I can think of a good way to structure that, but that will necessarily sequence all the operations and take longer to complete (no parallel network operations).

仅供参考,我将您的代码放入正在运行的jsFiddle中进行测试: http://jsfiddle.net/jfriend00/k49qbd3z/.我只需要删除一个.then(fn),因为您提供的代码中没有这样的fn.

FYI, I put your code into a running jsFiddle here for testing purposes: http://jsfiddle.net/jfriend00/k49qbd3z/. I just had to remove one .then(fn) because there was no such fn in the code you provided.

您可以通过将{concurrency: 1}添加到P.map()强制其一次仅执行一项操作来获得请求的输出.

You can get the requested output by adding {concurrency: 1} to P.map() to force it to only do one operation at a time.

// 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/与此相关输出:

See working demo here: http://jsfiddle.net/jfriend00/wshLu0g5/ with this output:

Fetching initial list
Fetching by ID
Saving
Fetching by ID
Saving
Fetching by ID
Saving

请记住,这很可能会严重降低最终结果的速度,因为您要按ID序列化所有提取操作,并且一次只能保存一个操作.获取一个ID的数据,然后保存,然后获取下一个ID的数据,然后保存,然后获取下一个ID的数据,然后保存,依此类推.

Keep in mind that this will likely seriously slow down the end result because you're serializing all fetching by id and saving to only one operation at a time. Fetch data for one id, then save it, then fetch data for next id, then save it, then fetch data for next id, then save it and so on.

这篇关于序贯的承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆