当前位置: 首页 > 知识库问答 >
问题:

javascript - 关于forEach里的异步?

督建柏
2023-12-22

以下这段代码为何先输出222,后输出111,如果想让111先输出应如何修改?

  this.items.forEach(async el => {      await ApiHelper.post(`/mainData/selectDateByCd/${el.cd}`)          .then(response => {            console.log("111");            if (response.data.length > 0) {              this.flag = true;            }          })          .catch(err => {            err;          });  })  console.log(222);

image.png

共有6个答案

陈龙野
2023-12-22

直接用 for ... of 就好,何必要去折腾 forEach()。另外,既然已经用了 await,就不需要再用 then 了。

for (const el of this.items) {    try {        const response = await ApiHelper.post(`/mainData/selectDateByCd/${el.cd}`);        console.log("111");        if (response.data.length > 0) {            this.flag = true;        }    } catch (err) {        console.log(err);    }}

如果不想用 try...catch,用 .catch() 来处理错误也可以。把有错误的用 catch() 处理掉之后,返回个正常值出来(没返回就是 undefined,注意在取到 response 值的时候进行区分处理,下面的代码是用 ?. 来处理的)

for (const el of this.items) {    const response = await ApiHelper.post(`/mainData/selectDateByCd/${el.cd}`)        .catch(err => {            console.log(err);            // return undefined;        });    if (response?.data.length > 0) {        this.flag = true;    }}
太叔京
2023-12-22

使用promise.all:

async function processData() {  const promises = this.items.map(el => {    return ApiHelper.post(`/mainData/selectDateByCd/${el.cd}`)      .then(response => {        console.log("111");        if (response.data.length > 0) {          this.flag = true;        }      })      .catch(err => {        err;      });  });  await Promise.all(promises);  console.log(222);}processData();

或者使用for of

async function processData() {  const promises = this.items.map(el => {    return ApiHelper.post(`/mainData/selectDateByCd/${el.cd}`)      .then(response => {        console.log("111");        if (response.data.length > 0) {          this.flag = true;        }      })      .catch(err => {        err;      });  });  await Promise.all(promises);  console.log(222);}processData();
阎令
2023-12-22

不如在外面加个 Promise

let  Promise = new Promise((res,rej)=>{   this.items.forEach(async el => {        await ApiHelper.post(`/mainData/selectDateByCd/${el.cd}`)            .then(response => {              console.log("111");              res(1)              if (response.data.length > 0) {                this.flag = true;              }            })            .catch(err => {              err;            });    }) })Promise.then(()=>{    console.log(222);})
冀子石
2023-12-22

在外包裹一层 Promise,可以确保执行顺序。

这种情况下,解决方案不唯一,我偏向于 Promise.all() + Array.map() 配合使用。

(async () => {  await Promise.all(    [10, 20, 30].map((el) => {      return new Promise((resolve) => {        setTimeout(() => {          // console.log("111");          console.log(el);          resolve(el);        }, 100 * el);      });    })  );  console.log(222);})();
端木兴国
2023-12-22

MDN有这么一段话image.png
要解决可以使用forfor...offor await...of

琴正初
2023-12-22

关于forEach里的异步?

以下这段代码为何先输出222,后输出111,如果想让111先输出应如何修改?

this.items.forEach(async el => {    await ApiHelper.post(`/mainData/selectDateByCd/${el.cd}`)        .then(response => {            console.log("111");            if (response.data.length > 0) {                this.flag = true;            }        })        .catch(err => {            err;        });})console.log(222);

对于你提出的问题,原因在于 forEach 遍历数组时是异步的,而 await 关键字则会暂停当前的 async 函数并等待 Promise 完成后继续执行。因此,当 forEach 遍历到第二个元素时,它不会等待第一个 Promise 完成就开始执行第二个,以此类推。因此,你看到的是先输出 222,然后是所有的 111

如果你想让 111 先输出,你可以使用 for...of 循环代替 forEach,因为 for...of 会等待 Promise 完成后再继续下一次循环。修改后的代码如下:

for (const el of this.items) {    await ApiHelper.post(`/mainData/selectDateByCd/${el.cd}`)        .then(response => {            console.log("111");            if (response.data.length > 0) {                this.flag = true;            }        })        .catch(err => {            err;        });}console.log(222);
 类似资料:
  • 以下代码在 chrome 输出 1,2,3 这个在网上找到了,forEach 一开始就已经获取了 数组长度 The range of elements processed by forEach is set before the first call to callbackfn. Elements which are appended to the array after the call to

  • 问题内容: 在循环中使用/ 是否有任何问题?我试图遍历文件数组和每个文件的内容。 这段代码确实有效,但是这可能会出问题吗?我让某人告诉我,您不应该在这样的高阶函数中使用/ ,所以我只是想问一下这是否有问题。 问题答案: 确保代码确实有效,但是我很确定它不会实现您期望的功能。它只会触发多个异步调用,但此后函数会立即返回。 顺序阅读 如果要顺序读取文件, 则不能使用。只需使用现代循环即可,该循环将按预

  • 大佬们,我使用puppeteer里的方法$$eval去爬一下页面的数据,结果发现引入的nanoid不能使用,刚开始还以为是nanoid不支持commonJS写法导致的,结果调试发现在eval函数外使用可以打印成功,eval里使用就报错了 注意:$$eval返回一个promise 报的错误: 有大佬知道为什么吗

  • 我想并行处理一个集合,但我在实现它时遇到了困难,因此我希望得到一些帮助。 foreach方法的原型采用作为参数,但我希望它等待异步lambda。

  • 问题内容: 如何在异步forEach循环后添加回调函数? 这里是一些更好的上下文: 控制器: 服务: 问题答案: 正如安德鲁所说,使用和延迟对象应该可以使您实现目标。 您想使用 这将确保您的所有promise对象都已解析,然后您可以回叫 jsfiddle上的示例 可以,但不能通话 使用延迟对象,您可以访问Promise,在此可以一起更改连续的调用。解析延迟的对象时,它将执行foreach,然后执行

  • 问题内容: 我知道编程的含义以及何时使用它。Java中有关键字吗?我试图找到一个关键字列表,但只有而没有。 问题答案: foreach不是Java关键字(IDE可以识别它并将“ For- each ”循环放入)。