嵌套的Promise结构顺序

时间:2017-06-21 15:39:42

标签: javascript angular loops typescript promise

我试图做一些有点棘手的事情,因为我还不习惯承诺。

我想填写<Id, ObjectInfo>

的地图

我有两个API点:

  • 一个获得所有用户
  • 另一个获取ID为
  • 的ObjectInfo

这就是我所拥有的:

const result: Map<string, String[]> = new Map();
return this.http.get(this.adress + '/', this.options).toPromise()
  .then((response) => {
    for (const id of response.json()){
      this.http.get(this.adress + '/' + id + '/properties').toPromise()
      .then((rep) => {
        result.set(id, rep.json());
        console.log('#1: ', result);
      }).catch(this.handleError)
    }
  })
  .then(() => console.log('#2: ', result))
  .then(() => result)
  .catch(this.handleError);

所以在这里,我希望#1在控制台中跟随#2,但事实并非如此。我知道我应该尝试Promise.all(),但我真的不知道如何设置它,因为我在嵌套循环中创建了Promise。

这是一个Angular项目,实际代码到目前为止工作,但抛出 ExpressionChangedAfterItHasBeenCheckedError
为了避免这种情况,改变我的诺言功能应该可以解决问题。

1 个答案:

答案 0 :(得分:4)

这部分代码

.then((response) => {
  // <-- HERE -->
  // this function must return a promise

  for (const id of response.json()){
    // ...
  }
})
.then(() => {
  // right now, this function executes **before** the requests
  // in the promise above are resolved
});

必须返回一个解析其中所有单个promise(在循环中构建的promise)的promise,因此promise链可以拥有你想要的顺序 - 在循环之前等待循环中的所有promise。

在这里使用Promise.all是很自然的,只需用数组映射替换for..of

.then((response) => {
  return Promise.all(
    Array
      .from(response.json())
      .map(id => {
        return this.http.get(this.adress + '/' + id + '/properties')
          .toPromise()
          .then((rep) => {
            result.set(id, rep.json());
            console.log('#1: ', result);
          })
          .catch(this.handleError)
      })
  );
})
.then(...)