javascript - 很难理解这个在 JavaScript 中检索多个用户信息的 Promise + async wait 示例

标签 javascript asynchronous ecmascript-6 async-await frontend

正在遵循本教程( https://javascript.info/fetch )有关 javascript 的 Promise 和 async wait 的内容,但无法理解它提供的练习。

问题是关于从 Github 检索多个用户信息。每个用户一个提取请求。 并且请求不应该互相等待。以便数据尽快到达。

它提供的解决方案是

async function getUsers(names) {
  let jobs = [];

  for(let name of names) {
    let job = fetch(`https://api.github.com/users/${name}`).then(
      successResponse => {
        if (successResponse.status != 200) {
          return null;
        } else {
          return successResponse.json();
        }
      },
      failResponse => {
        return null;
      }
    );
    jobs.push(job);
  }

  let results = await Promise.all(jobs);

  return results;
}

我的第一个问题是,我们可以使用 await 来获取数据吗?即以下代码片段是否等同于他提供的解决方案?

async function getUsers2(names) {
  let jobs = [];

  for(let name of names) {
    let response
    try {
      response = await fetch(`https://api.github.com/users/${name}`);
    } catch(e) {
      response = null
    }
    const job = response && response.json()
    jobs.push(job);
  }

  let results = await Promise.all(jobs);

  return results;
} 

此外,教程说

.then call is attached directly to fetch, so that when we have the response, it doesn’t wait for other fetches, but starts to read .json() immediately.

If we used await Promise.all(names.map(name => fetch(...))), and call .json() on the results, then it would wait for all fetches to respond. By adding .json() directly to each fetch, we ensure that individual fetches start reading data as JSON without waiting for each other.

他的意思是如果我们这样写解决方案

async function getUser(name) {
  const response = await fetch(`https://api.github.com/users/${name}`)

  return response.ok ? await response.json : null
}

async function getUsers(names) {
  return await Promise.all(names.map(name => getUser(name)))
}

我们无法达到我们不希望请求不互相等待的效果吗?

最佳答案

My first question is, can we use await for the fetch. i.e. is the following snippet equivalent to the solution he provided?

没有。当在异步函数的直接主体中时,只要有 await ,该函数将完全暂停,直到下面的 Promise 解析。所以,循环

  for(let name of names) {
    let response
    try {
      response = await fetch(`https://api.github.com/users/${name}`);
    } catch(e) {
      response = null
    }

需要连续等待接收每个响应的 header ,然后才能继续初始化下一个请求。

Does he mean that if we write the solution this way

首先需要调整语法:.json是一个方法,所以需要调用它:

async function getUser(name) {
  const response = await fetch(`https://api.github.com/users/${name}`)
  return response.ok ? await response.json() : null
  //                                      ^^
}

但这完全没问题。唯一awaitgetUsers函数正在等待整个 Promise.all解决; .map将阵列 ping 至 getUser调用是同步进行的,因此所有请求都会立即发出,因此任何网络请求都不需要等待其他任何请求完成才能工作。

作者提到的问题是调用 Promise.allfetch 的数组上调用,而不是 .json() 的数组来电:

// Bad, do not use:
const getUsers = async (names) => {
  const responses = await Promise.all(names.map(
    name => fetch(`https://api.github.com/users/${name}`)
  ));
  return Promise.all(responses.map(
    response => response.ok ? response.json() : null
  ));
}

上述问题在于,脚本必须等待收到每个请求的所有响应 header ,然后才能开始解析其中任何一个请求的响应正文。

另一个并行解决方案:

const getUsers = names => Promise.all(names.map(
  async (name) => {
    const res = await fetch(`https://api.github.com/users/${name}`);
    return res.ok ? res.json() : null;
  }
));

关于javascript - 很难理解这个在 JavaScript 中检索多个用户信息的 Promise + async wait 示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60480566/

相关文章:

javascript - 自定义过滤器在 Angular Hybrid 应用程序中不起作用

javascript - JavaScript 列表操作是同步的吗?

javascript - 为什么异步函数返回值的 promise 而不是直接返回值?

javascript - 箭头函数 : destructuring arguments and grabbing them as a whole at the same time

JavaScript:css 切换到暗模式

javascript - 对于每个跨度数据,从 json 响应中获取 id 并检查 id

javascript - 如何选择DOM中除一个元素之外的所有元素?

reactjs - React JS - 为什么一个按钮被点击两次?

node.js - Node.js Express 中的异步代码

javascript - ECMAScript 6 的范围是什么?