从 API returns 未定义中获取结果

fetch result from API returns undefined

我正在尝试从 API 中获取数据,但结果一直未定义。我正在使用 promise.all 链接 API 调用,然后链接承诺对数据执行其他操作。我似乎无法将我的结果传递给州。

这是有问题的代码:

if (gameDifficulty === "mixed") {
  const result = await Promise.all([
    fetchClient.getData(
      getEndpoint(
        `amount=${countValues[0]}&difficulty=easy&type=${questionType}`
      )
    ),
    fetchClient.getData(
      getEndpoint(
        `amount=${countValues[1]}&difficulty=medium&type=${questionType}`
      )
    ),
    fetchClient.getData(
      getEndpoint(
        `amount=${countValues[2]}&difficulty=hard&type=${questionType}`
      )
    ),
  ])
    .then(function (responses) {
      console.log(responses);
      console.log(result); //returns undefined
      return Promise.all(
        responses.map(function (response, idx) {
          return fetchClient.processData(response, "results");
        })
      );
    })
    .then(function (data) {
      console.log(data);

      console.log(result); // returns undefined
      return [...data[0], ...data[1], ...data[2]];
    });
}

在您的浏览器中转到您的网络选项卡发送一个 api 请求并查看它是否正在发送任何飞行前请求?

飞行前请求将包含 OPTIONS 方法,因此您可以识别它

使用 async/await 语法使其变得简单。

避免将 async/awaitthen/catch 风格混合。

const getDataResponses = await Promise.all([
  fetchClient.getData(
    getEndpoint(
      `amount=${countValues[0]}&difficulty=easy&type=${questionType}`
    )
  ),
  fetchClient.getData(
    getEndpoint(
      `amount=${countValues[1]}&difficulty=medium&type=${questionType}`
    )
  ),
  fetchClient.getData(
    getEndpoint(
      `amount=${countValues[2]}&difficulty=hard&type=${questionType}`
    )
  ),
]);

const data = await Promise.all(
  getDataResponse.map((response) => {
    return fetchClient.processData(response, "results");
  })
);

console.log('getDataResponses', getDataResponses);
console.log('processDataResponse', data);
return [...data[0], ...data[1], ...data[2]];

由于 resultPromise 上直接从 await 获取值,您可以使用它代替 .then()

const responses = await Promise.all([
    fetchClient.getData(
        getEndpoint(
            `amount=${countValues[0]}&difficulty=easy&type=${questionType}`
        )
    ),
    fetchClient.getData(
        getEndpoint(
            `amount=${countValues[1]}&difficulty=medium&type=${questionType}`
        )
    ),
    fetchClient.getData(
        getEndpoint(
            `amount=${countValues[2]}&difficulty=hard&type=${questionType}`
        )
    ),
])

console.log('responses', responses);

const data = await Promise.all(
    responses.map(function (response, idx) {
        return fetchClient.processData(response, "results");
    })
);

console.log('data', data);
console.log([...data[0], ...data[1], ...data[2]]);

其他答案显示了如何更正代码,同时避免混合使用承诺链和 await 运算符。这个答案是关于为什么会出现 result 的未定义值:

 const result = await <promise chain>

在执行 await 操作数之前为 result 创建一个绑定。与所有简单变量定义一样,它以 undefined 的值开始,并且因为它现在存在,所以在后面的代码中访问 result 不会产生错误。

promise 链的对象值是由链中最后一个 promise 方法(即 thencatchfinally)调用的 returnpromise .这是 await 操作数在 return 将其(成功)值作为 await 表达式的值之前等待稳定的承诺。

因此 await 直到最后一个 then 处理程序 return 之后才 return 将值分配给 result,这意味着在匿名之后在

中发挥作用
.then(function (data) {
  console.log(data);

  console.log(result); // returns undefined
  return [...data[0], ...data[1], ...data[2]];
});

已完成执行和 returns。在那之前,所有 console.log(result) 调用 log undefined 因为没有分配给 result 发生。


TLDR;

附加到 promise 的处理程序异步执行,在事件循环的新调用中,在它们附加到的 promise 被履行或拒绝后。

await 是一元运算符,能够将执行状态和 return 保存到事件循环中,直到其承诺操作数被确定。

贴出代码的操作顺序是

  1. 定义result,将其初始化为undefined并设置await运算符以获取return由then 在步骤 5.

  2. 发出三个端点数据请求。

  3. 使用 Promise.all 从步骤 2 中获取一组响应。

  4. (then) 使用Promise.all 从步骤 3 的结果中异步获取数组中每个响应的过程数据数组。

  5. (然后)展平来自步骤 4 的数据数组和return展平的数组

  6. (然后)await 运算符得到一个带有第 5 步结果的回调,return将其作为 await 表达式的值

  7. 第 6 步中的 return 值用于初始化 const result 声明。从语法上讲,这发生在 const result 语句结束之前,但实际上已经扩展到多个网络请求和事件循环调用所需的时间。