【问题标题】:NodeJS: Chain functions automatically in a promise?NodeJS:在 Promise 中自动执行链式函数?
【发布时间】:2022-02-16 10:07:17
【问题描述】:

我目前正在从 API 获取数据,并且需要执行多个 GET 请求(使用 axios)。在所有这些 GET 请求完成后,我返回一个已解决的承诺。

但是,我需要根据数组列表自动执行这些 GET 请求:

    function do_api_get_requests() {

        return promise = new Promise(function(resolve, reject) {

          API_IDs = [0, 1, 2];

          axios.get('https://my.api.com/' + API_IDs[0])
          .then(data => {
            // Do something with data

            axios.get('https://my.api.com/' + API_IDs[1])
            .then(data => {
              // Do something with data

              axios.get('https://my.api.com/' + API_IDs[2])
              .then(data => {
                // Do something with data
                
                // Finished, resolve
                resolve("success");
                
              }


            }


          }

        }

    }

这可行,但问题是 API_IDs 并不总是相同的数组,它会改变。所以我不确定如何自动链接这些请求。

【问题讨论】:

  • 请求需要按顺序进行还是可以并发执行?
  • 没有async/await,使用递归方法。将您仍需要访问的 api id 作为参数传递。
  • 仅供参考,如果您显示真实代码,包括请求的相关处理以及调用者如何使用它,而不是伪代码,人们可以更好地帮助您。这适用于这里的所有问题,而不仅仅是这个问题。

标签: javascript node.js promise es6-promise chain


【解决方案1】:

既然你说它可能是一个可变长度的数组并且你展示了请求的顺序,你可以使用 async/await 循环遍历数组:

async function do_api_get_requests(API_IDS) {
    for (let id of API_IDS) {
        const data = await axios.get(`https://my.api.com/${id}`);
        // do something with data here
    }
    return "success";
}

而且,由于您说 API id 列表是可变的,所以我将其设置为可以传递给函数的参数。


如果您想并行运行所有 API 请求(这对于小型阵列可能没问题,但对于大型阵列可能会很麻烦)并且您不需要按特定顺序运行它们,您可以这样做这个:

function do_api_get_requests(API_IDS) {
    return Promise.all(API_IDS.map(async (id) => {
        const data = await axios.get(`https://my.api.com/${id}`);
        // do something with data here for this request
    })).then(() => {
        // make resolved value be "success"
        return "success";
    });
}

根据您的具体情况,您也可以使用Promise.allSettled()。由于您没有显示返回结果,因此尚不清楚这是否有用。

【讨论】:

  • 我会用 Promise.all() 优化它,这样他就不会等待每个响应才能继续。
  • @NeNaD - 我已经将其添加为选项。并行运行它们是否是一个好主意完全取决于情况。有时后续结果取决于先前的结果。有时,数组可能很大,您实际上并不希望有那么多请求同时运行或一次全部命中目标服务器。有时,您希望迭代在第一个失败时停止,而不是全部启动。它高度依赖于情况。
  • @NeNaD - OP 说 “API_IDs 并不总是相同的数组” 很难知道它会或赢得什么不是。无论如何,我提供了两种选择。
  • Promise.all() 的问题是,如果其中任何一个 Promise 被拒绝,它将自动拒绝 Promise.all()。如果所有请求都很重要,则可以使用 Promise.allSettled() 代替,这样就可以在出现任何错误时递归运行。
  • @guilfer - Promise.allSettled() 在您想知道哪些调用成功,哪些调用失败以及在某些调用失败时获得任何成功结果时很有用。 OP在他们的问题中没有显示任何这些。但是,我在答案中将其作为一个选项提及。
【解决方案2】:

您可以使用Promise.all()方法同时做所有的API请求,并在所有请求都解决后解决。

function do_api_get_requests() {
  const API_IDs = [0, 1, 2];

  let promises = [];
  for (const id of API_IDS) {
    promises.push(axios.get(`https://my.api.com/${id}`));
  }

  return Promise.all(promises);
}

【讨论】:

    【解决方案3】:

    如果你使用 Bluebird.js(一个更好的 Promise 库,并且比内置的 Promise 更快),你可以使用 Promise.each()Promise.mapSeries()Promisme.reduce() 来做你想做的事。

    http://bluebirdjs.com

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-21
      • 1970-01-01
      • 2021-05-31
      • 1970-01-01
      相关资源
      最近更新 更多