Почему я не могу переместить «жду» в другие части моего кода? - PullRequest
0 голосов
/ 05 апреля 2019

Edit2: решение внизу

Я использую Chrome-консоль и пытаюсь вывести извлеченные данные, и я получаю желаемый результат, только написав «await» в нужном месте, даже если другое решение может сделать это раньше, а я нет знать, почему / как это работает.

solution () - это «официальное» решение веб-курса, которым я занимаюсь. В настоящее время обе функции возвращают одно и то же. В myFunction я пытался написать «await» перед каждой используемой функцией и сделать каждую функцию «асинхронной», но я все еще не могу заменить «await» внутри журнала, хотя другое решение может.

const urls = ['https://jsonplaceholder.typicode.com/users']

const myFunction = async function() {
                                          // tried await before urls/fetch (+ make it async)
   const arrfetched = urls.map(  url => fetch(url) );   
   const [ users ] = arrfetched.map( async fetched => {  //tried await in front of arrfetched
       return (await fetched).json();                   //tried await right after return
   });
   console.log('users', await users);                   // but can't get rid of this await
}

const solution = async function() {

  const [ users ] = await Promise.all(urls.map(async function(url) {
      const response = await fetch(url);
      return response.json();
  }));
  console.log('users', users);                          // none here, so it can be done 
}

solution();
myFunction();

Я думаю, что "ожидание" работает таким образом, что:

   const a = await b;
   console.log(a);       // this doesn't work

так же, как

   const a = b;
   console.log(await a); // this works

но это не так, и я не понимаю, почему нет. Я чувствую, что Promise.all делает что-то неожиданное, поскольку просто написать «await» в объявлении нельзя, только после объявления.

Edit1: это не работает

const myFunction = async function() {

    const arrfetched = await urls.map( async url => await fetch(url) );
    const [ users ] = await arrfetched.map( async fetched => {
        return await (await fetched).json();
    });
    console.log('users', users);
}

Edit2: Спасибо за помощь всем , я пытался поставить ".toString ()" на многие переменные и переключаться там, где я вставил "await" в код и где не. Насколько я понимаю, если я не использую Promise.all, тогда мне нужно ждать каждый раз, когда я хочу использовать (как в реальных данных, а не просто использовать) функцию или переменную, которая имеет обещания . Недостаточно только ждать, когда данные будут обрабатываться, а не подниматься дальше. В приведенном выше редакторе Edit1 пользователи запускаются до завершения любого другого ожидания, поэтому независимо от того, сколько я ожидаю записи, ни одно из них не выполняется. Копирование этого кода в (в моем случае chrome-) консоль прекрасно демонстрирует это:

const urls = [
      'https://jsonplaceholder.typicode.com/users',
    ]
    const myFunction = async function() {

      const arrfetched =  urls.map( async url => fetch(url) );
      const [ users ] =  arrfetched.map( async fetched => {
          console.log('fetched', fetched);
          console.log('fetched wait', await fetched);
          return (await fetched).json();
      });
      console.log('users', users);
      console.log('users wait', await users);
    }

    myFunction();

// Output in the order below:
// fetched()
// users()
// fetched wait()
// users wait()

Ответы [ 3 ]

0 голосов
/ 05 апреля 2019

TL;ДР: Promise.all там важно, но в этом нет ничего волшебного.Он просто преобразует массив Обещаний в Обещание, которое разрешается с помощью массива.

Давайте разберемся myFunction:

const arrfetched = urls.map(  url => fetch(url) );

Это возвращает массив Обещаний, пока все хорошо.


const [ users] = arrfetched.map( async fetched => {
  return (await fetched).json();
});

Вы деструктурируете массив, чтобы получить первый член, поэтому он такой же, как этот:

const arr = arrfetched.map( async fetched => {
  return (await fetched).json();
});
const users = arr[0];

Здесь мы преобразуем массив обещаний в другоймассив обещаний.Обратите внимание, что вызов map с функцией async всегда приведет к массиву Promises.

Затем вы перемещаете первый член этого массива в users, поэтому users теперь фактически содержит одинPromise.Затем вы ждете его перед печатью:

console.log('users', await users);

В отличие от этого, другой фрагмент делает здесь что-то немного другое:

const [ users ] = await Promise.all(urls.map(async function(url) {
  const response = await fetch(url);
  return response.json();
}));

Еще раз, давайте отделим деструктуризацию:

const arr = await Promise.all(urls.map(async function(url) {
  const response = await fetch(url);
  return response.json();
}));
const users = arr[0];

Promise.all преобразует массив Обещаний в одно Обещание, которое приводит к массиву.Это означает, что после await Promise.all все в arr ожидается (вы можете представить await Promise.all как цикл, который ожидает все в массиве).Это означает, что arr является просто обычным массивом (не массивом Обещаний), и, таким образом, users уже ожидается, или, скорее, он никогда не был Обещанием, и, следовательно, вам не нужно await это.

0 голосов
/ 05 апреля 2019

Возможно, самый простой способ объяснить это - разбить то, что достигает каждый шаг:

const urls = ['https://jsonplaceholder.typicode.com/users']

async function myFunction() {

  // You can definitely use `map` to `fetch` the urls
  // but remember that `fetch` is a method that returns a promise
  // so you'll just be left with an array filled with promises that
  // are waiting to be resolved.
  const arrfetched = urls.map(url => fetch(url));

  // `Promise.all` is the most convenient way to wait til everything's resolved
  // and it _also_ returns a promise. We can use `await` to wait for that 
  // to complete.
  const responses = await Promise.all(arrfetched);

  // We now have an array of resolved promises, and we can, again, use `map`
  // to iterate over them to return JSON. `json()` _also_ returns a promise
  // so again you'll be left with an array of unresolved promises...
  const userData = responses.map(fetched => fetched.json());

  //...so we wait for those too, and destructure out the first array element
  const [users] = await Promise.all(userData);

  //... et voila!
  console.log(users);
}

myFunction();
0 голосов
/ 05 апреля 2019

Ожидание может использоваться только в асинхронной функции. Жду зарезервированный ключ. Вы не можете ждать чего-то, если это не асинхронно. Вот почему он работает в console.log, но не в глобальной области видимости.

...