微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从 API 获取结果返回未定义

如何解决从 API 获取结果返回未定义

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

这是违规代码

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]];
,

由于 result 直接从 await 上的 Promise 获取值,因此您可以使用它代替 .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[2]]);
,

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

 const result = await <promise chain>

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

promise 链的对象值是链中调用的最后一个promise 方法(即thencatchfinally)返回的promise。这是对 await 操作数在返回其(成功)值作为 await 表达式的值之前等待结算的承诺。

因此 await 直到最后一个 result 处理程序返回后才会返回要分配给 then 的值,这意味着在

中的匿名函数之后
.then(function (data) {
  console.log(data);

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

已完成执行并返回。在此之前,所有 console.log(result) 调用都记录 undefined,因为没有分配给 result


TLDR;

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

await 是一个一元运算符,能够保存执行状态并返回到事件循环,直到它的 promise 操作数变得稳定。

贴出代码的操作顺序是

  1. 定义result,将其初始化为undefined,并设置await操作符获取步骤5中then返回的promise结果。

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

  3. 使用 Promise.all 获取第 2 步的响应数组。

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

  5. (然后)将第 4 步中的数据数组展平并返回展平后的数组

  6. (然后)await 操作符获取第 5 步结果的回调,并将其作为 await 表达式的值返回

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。