【问题标题】:return Promise chain inside Promise then然后在 Promise 中返回 Promise 链
【发布时间】:2023-03-09 20:19:01
【问题描述】:

我想使用 axios 获取返回 objectId 数组列表的 API。获得列表 objectId 后,我想使用 promise 获取对象的详细信息

我想到了这样的事情

var objectDetail = [];

axios.get('apiendpoint/')
.then((response) => {
  var listOfObjectId = response.data;
  var chain = Promise.resolve()
  for (var objectId of listOfObjectId) {
    chain = chain.then(axios.get(`apiendpoint/${objectId}`)
      .then((response) => {
        objectDetail.push(response.data);
      })
    );
  }
  return chain;
}).then((chain) => {
  console.log(chain);
  return chain;
})

上面的代码返回未定义,承诺链对象没有传递给then方法调用。我的方法是错误的还是我错过了什么?谢谢

这是我读过的一些堆栈,可能是相关的:

【问题讨论】:

标签: javascript promise axios


【解决方案1】:

承诺链正在传递给最终的.then,但承诺链没有返回任何东西:看你的

.then((response) => {
  objectDetail.push(response.data);
})

那个函数不返回任何东西。如果您想在链的末尾使用objectDetail 而不引用外部变量,那么return 也可以:

.then((response) => {
  objectDetail.push(response.data);
  return objectDetail;
})

但请注意

}).then((chain) => {
  console.log(chain);
  return chain;
})

有点多余 - 除非你这样做只是为了log 结果,最好完全不使用它。

如果您改用Promise.all,您的代码会更清晰:

axios.get('apiendpoint/')
  .then(({ data }) => Promise.all(
    data.map(objectId => (axios.get(`apiendpoint/${objectId}`)
      .then(res => res.data)
    ))
  ));

【讨论】:

    【解决方案2】:

    你不能用承诺履行承诺。如果您从 then( onfulfilled) 处理程序中返回一个 Promise,则 Promise 代码会等待返回的 Promise解决,然后再使用返回的 Promise 的成功或失败值解决或拒绝链中的下一个 Promise .

    所以

    //...
      return chain;
    }).then((chain) => {
      console.log(chain);
      return chain;
    })
    

    令人困惑 - 在第一行返回的 chain 承诺不会传递给下一个 then 处理程序。传递的是成功完成后chain 中最后一个promise 的fulfilled 值。但是,由于chain 中的处理程序没有显式返回值,所以这将是undefined

    选项包括:

    • 出于调试目的,可选择在完整构造 chain 的值之后记录它,然后从第一个 then 处理程序返回 chain
    • 忽略传递给最终then成功处理程序的实际值,并使用它被调用来指示objectDetail包含有效数据,或者
    • 在第一个 then 处理程序中创建 objectDetail,并从构造期间添加到 chain 的 Promise 处理程序返回它。

      axios.get('apiendpoint/')
      .then((response) => {
          var listOfObjectId = response.data;
          var objectDetail = [];
          var chain = Promise.resolve()
          for (var objectId of listOfObjectId) {
              chain = chain.then(axios.get(`apiendpoint/${objectId}`)
              .then((response) => {
                  objectDetail.push(response.data);
                  return objectDetail; // return details array
              });
          }
          return chain;
      })
      .then( objectDetail) => {
          // process objectDetail
      })
      .catch(err=> console.log(err););
      

    上述方法按顺序处理详细请求。它可以使用Promise.all 重写,以便并行发出详细请求。

    【讨论】:

      猜你喜欢
      • 2017-04-30
      • 2018-03-25
      • 2020-11-28
      • 2021-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-15
      相关资源
      最近更新 更多