为什么我不能“等待”到我的代码的其他部分?

问题描述 投票:0回答:3

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”不能做同样的事情,只有在声明之后。

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()”放在很多变量上并切换到我在代码中放置“等待”的地方,而不是。据我了解,如果我不使用Promise.all那么我需要等待每次我想要使用(如在实际数据中,而不仅仅是使用)一个有承诺的函数或变量。仅仅等待数据被采购的地方是不够的,而不是更进一步。在上面的Edit1中,用户运行bevore任何其他await完成,因此无论我写入多少等待,都没有执行。在(在我的案例中为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()
javascript promise async-await
3个回答
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将Promise数组转换为单个Promise,从而生成一个数组。这意味着,在await Promise.all之后,arr中的所有东西都在等待(你可以想象await Promise.all就像一个等待阵列中所有东西的循环)。这意味着arr只是一个正常的数组(不是Promises数组),因此users已经等待,或者更确切地说,它从来就不是一个Promise,因此你不需要await它。


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

-1
投票

Await只能在异步函数中使用。 Await是一个保留密钥。如果它不是异步的话,你不能等待。这就是它在console.log中工作但不在全局范围内的原因。

© www.soinside.com 2019 - 2024. All rights reserved.