将promise作为.then()链的一部分进行映射

时间:2017-05-19 02:09:43

标签: javascript promise

我想做的事情:

我试图创建一个允许我抽象出来的函数:

somePromise(options)
  .then(anotherPromise)
  .then(results =>
    Promise.all(results.map(result =>
      someOtherPromise(result.url)
        .then(anotherPromise)
        .then(val => Object.assign(val, { hello: "world" }))
      )));

成:

somePromise(options)
  .then(anotherPromise)
  .thenMapAll(results, result =>
    someOtherPromise(result.url)
      .then(anotherPromise)
      .then(val => Object.assign(val, { hello: "world" }))
  );

,即抽象.thenMapAll函数,它代替.then将结果数组映射到Promise.all等待的所有承诺数组。

到目前为止我取得的成就:

此:

Promise.mapAll = (array, fn) => 
  Promise.all(array.map(val => fn(val)));

Promise.prototype.thenMapAll = (array, fn) => 
  Promise.mapAll(array, val => fn(val));

基本上有效!但是,Promises解决的顺序不正确。 .thenMap创建的Promise似乎总是与前面的任何.then相同:

new Promise((res, rej) => res("a"))
  .then(console.log) // Neither syntax makes a difference.
  .then(() => new Promise((res,rej) => res(console.log("b"))))
  .thenMapAll([ "c", "d", "e" ], console.log);

/* Outputs: 
**   c
**   d
**   e
**   a
**   b
*/

问题!

为什么Promises的顺序不正确?如何让Promises以正确的顺序运行?

2 个答案:

答案 0 :(得分:3)

正在调用

thenMapAll,而不是将其承诺添加到当前的承诺链,你想要的是:

Promise.mapAll = (array, fn) => 
  Promise.all(array.map(val => fn(val)));

Promise.prototype.thenMapAll = function(array, fn) {
  return this.then(() => {
    return Promise.mapAll(array, val => fn(val));
  });
};

输出:

a
b
c
d
e

因为现在thenMapAll正在调用Promise.mapAll来调用this.then(() => {}),这会将其添加到现有的承诺链,而不是创建一个立即运行的全新承诺链。由于我们向Promise.prototype添加了一个函数,this关键字引用了当前的Promise实例,因此这就是我们被允许以这种方式添加到promise链的原因。

答案 1 :(得分:0)

您所需的语法出错:results未定义。它应该来自调用方法的承诺 - 它是结果值 - 所以你应该省略参数:

somePromise(options)
  .then(anotherPromise)
  .thenMapAll(  result =>
//            ^
    someOtherPromise(result.url)
      .then(anotherPromise)
      .then(val => Object.assign(val, { hello: "world" }))
  );

在您的thenMapAll方法中,您需要等待接收方承诺(this)才能通过安装then处理程序来获得此结果:

Promise.mapAll = (array, fn) => Promise.all(array.map(fn));
Promise.prototype.thenMapAll = function(fn) {
  return this.then(array => Promise.mapAll(array, fn));
};