如何展平嵌套的promise依赖项?

时间:2016-04-23 01:06:29

标签: javascript meteor promise

我通过节点应用程序使用mondora/asteroid通过承诺模式使用Meteor DDP。

我将以下代码从回调样式重写为承诺样式,但我仍然坚持如何展平它。

asteroid.call('Pony.search', { params })
  .then(res => {
    if (res.length === 1) {
      // something
      asteroid.call('Pony.finish', { params })
        // this part feels wrong
        .then(res => {
          // something else
        });
    } else {
      // nope
    }
  })
  .catch(err => {
    console.error(err);
  });

还有第二个asteroid.call&第一个承诺响应中的then是一个承诺。这部分感觉不对,就像它应该是扁平的而不是嵌套但我不知道如何到达那里。

编辑:

结束使用这样的事情(仍然没有决定是否有第一个然后检查if length === 1并可能立即拒绝它。任何人都知道什么是最佳做法?

asteroid.call('Pony.search', { params })
  .then(res => res.length === 1 ? res : Promise.reject())
  .then(res => asteroid.call('Pony.finish', { res[0].something }))
  .then(res => {
    // do something
  })
  .catch(err => {
    // handle the no found
    console.error(err);
  });

2 个答案:

答案 0 :(得分:1)

而不是嵌套回调,链接承诺与.then()

注意:

我不确定你正在使用什么Promise库,但是想法是从第一个.then()返回被拒绝的promise,如果有错误,否则你会返回一个成功的promise。然后,promise库将为您处理错误处理,如果存在被拒绝的promise,则转到catch块。

asteroid.call('Pony.search', { params })
  .then(res => {
    res.length === 1 ? return asteroid.call('Pony.finish', { params }) : Promise.reject();
  })
  .then(res => {
    //do stuff here
  })
  .catch(err => {
    console.error(err);
  });

编辑:

唯一的问题是当您需要同时访问承诺中的返回值的两个时。当你扁平化承诺链时,你将失去对先前承诺的结果的访问权。

您有几个选择:

  1. 如果你不需要以前的结果,那就像我在这里一样平掉承诺链
  2. 如果确实需要以前的值

    2a上。而且你不关心执行的顺序,然后使用Promise.all([promise1, promise2])

    2B。而且你确实关心执行的顺序,那么你必须像你最初那样使用嵌套的promises。

答案 1 :(得分:0)

如果promises是嵌套的,则promises和callback之间没有区别。

尝试更改代码以使用保证链:

asteroid.call('Pony.search', { params })
  .then(res => {
    if (res.length === 1) {
      // something
      let p1 = asteroid.call('Pony.finish', { params });
      return p1;
    }
    else {
      // nope
    }
  })

  .then (function SomeThingElse(res2){
    // something else
    // res2 is return value from nested asteroid.call

  })

  .catch(err => {
    console.error(err);
  });

由于第一个解析处理程序返回Promise p1,因此链中的下一个函数(function SomeThingElse)的调用将推迟到p1resolved

现在扩展这个例子:

asteroid.call('Pony.search', { params })
  .then(res => {
    if (res.length === 1) {
      // something
      let p1 = asteroid.call('Pony.finish', { params });
      return p1;
    }
    else {
      // nope
    }
  })

  .then (function SomeThingElse(res2){
    // something else
    // res2 is return value from nested asteroid.call

  })

  .then (function AnotherFunc(res3){

  })

  .catch(err => {
    console.error(err);
  });

如果SomeThingElse返回Promise,则AnotherFunc的调用会延迟,直到该承诺得到解决。

如果SomeThingElse 返回Promise,则会立即使用与收到的“SomeThingElse”相同的参数调用AnotherFunc。换句话说,当p1被解析时,SomeThingElseAnotherFunc都会被调用。