С трудом понимая это обещание + asyn c, ждите пример для получения информации о нескольких пользователях в JavaScript - PullRequest
0 голосов
/ 02 марта 2020

следовал этому уроку (https://javascript.info/fetch) по обещанию javascript и asyn c, ожидают и испытывает затруднения при понимании упражнения, которое он предоставил.

Вопрос о получение информации о нескольких пользователях из 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 вызов присоединяется непосредственно к fetch, так что когда у нас есть ответ, он не ждет других извлечений, но сразу начинает читать. json ().

Если мы использовали await Promise.all (names.map (name => fetch (...)) )) и вызовите. json () для результатов, тогда он будет ждать ответа всех выборок. Добавляя. json () непосредственно к каждой выборке, мы гарантируем, что отдельные выборки начнут читать данные как JSON, не ожидая друг друга.

Имеет ли он в виду, что если мы напишем решение, то это кстати

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)))
}

мы не смогли бы добиться такого эффекта, чтобы мы не хотели, чтобы запросы не ждали друг друга?

1 Ответ

3 голосов
/ 02 марта 2020

Мой первый вопрос: можем ли мы использовать ожидание для получения. то есть следующий фрагмент эквивалентен предоставленному им решению?

Нет. Когда в непосредственном теле функции asyn c, когда есть await, функция будет полностью приостановлена, пока не выполнится следующее обещание. Таким образом, l oop

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

нужно дождаться в последовательном , чтобы получить заголовки каждого ответа, прежде чем продолжать инициализацию следующего запроса.

Имеет ли он в виду, что если мы напишем решение таким образом

Во-первых, необходимо скорректировать синтаксис: .json - это метод, поэтому его нужно вызывать:

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

Но это прекрасно. Единственный await в функции getUsers ожидает разрешения целом Promise.all; .map пинг массива до вызова getUser выполняется синхронно, поэтому все запросы отправляются одновременно, поэтому ни одному из сетевых запросов не нужно ждать, пока какой-либо другой запрос не завершится sh, чтобы работа.

Проблема, на которую ссылался автор, - вызывать Promise.all для массива вызовов fetch, а не для массива вызовов .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
  ));
}

Проблема с вышесказанным заключается в том, что сценарий должен ожидать получения всех заголовков ответа от каждого запроса, прежде чем можно будет проанализировать тело ответа для любого из них.

Другое параллельное решение:

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;
  }
));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...