为什么不能将“ await”移到代码的其他部分?

时间:2019-04-05 12:01:13

标签: javascript promise async-await

Edit2:底部的解决方案

我正在使用chrome-console,并且尝试输出提取的数据,尽管只有另一种解决方案可以做到,但我只能通过在正确的位置编写“ 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”是不可能的。

编辑1:这不起作用

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。那么每次我想使用(如实际数据,而不仅仅是使用)具有承诺的函数或变量时,都需要等待强>。仅等待正在处理数据的地方而不是进一步处理是不够的。 在上面的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 :(得分:0)

TL; DR:Promise.all在这里很重要,但这没什么神奇的。它只是将一个Promises数组转换为一个可以通过数组解析的Promise。

让我们分解myFunction

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

这将返回一个Promises数组,到目前为止都很好。


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将Promises数组转换为单个Promise,从而生成一个数组。这意味着在await Promise.all之后,arr中的所有内容都已被等待(您可以想象await Promise.all就像一个等待数组中所有内容的循环)。这意味着arr只是一个普通的数组(不是Promises的数组),因此users已经在等待,或者说,它从来不是一个Promise,因此您不需要需要await

答案 1 :(得分:0)

也许最简单的解释方法是分解每个步骤所能达到的目标:

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();

答案 2 :(得分:-1)

等待只能在异步功能中使用。等待是保留键。如果它不是异步的,您就不能等待。因此,它可以在console.log中工作,但不能在全局范围内工作。