map/forEach循环里async、await为什么会失效

本文探讨了async/await在map/forEach循环中为何未能按预期同步执行的原因,并提供了两种解决方案:使用for循环和利用Promise.all()。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

第一次在forEach循环里写请求用了async和await后,发现请求并没有同步执行(也就是async和await没有生效),真的是百思不得其解,下面就说一下为什么会这样和解决方法。

一、为什么map/forEach循环里async、await没有生效

原因:map/forEach内部使用了while结合callback方式来执行函数,await不会等待callback的执行
示例如下:

    const arr = [1, 2, 3, 4];
    
    const request = (num) => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(num);
          console.log(`执行${num}`);
        }, 1000);
      });
    };

    //forEach循环请求(这种方式有问题)
    arr.forEach(async (v) => {
      console.log('调用请求之前', v);
      const res = await request(v);
      console.log('调用请求之后', v);
    });

运行结果如下:
在这里插入图片描述

而我们期望的是如下:
在这里插入图片描述

二、解决方法

1.用for循环

   const handleRequest = async () => {
      for (let i = 0; i < arr.length; i++) {
        console.log('调用请求之前', arr[i]);
        const res = await request(arr[i]);
        console.log('调用请求之后', arr[i]);
      }
    };
   handleRequest();

2.用promise.all()

 const handleRequest = async () => {
      const resArr = await Promise.all(
        arr.map(async (v) => {
          const res = await request(v);
          console.log(`调用请求之后,${res}`);
          return res;
        })
      );
      return resArr;
   };
  handleRequest();

总结

工作中遇到的小问题,有什么不对的地方还请给与评价

// ==UserScript== // @name YouTube评论词频统计(控制台输出) // @namespace http://tampermonkey.net/ // @version 0.1 // @description 统计当前视频评论区词频,控制台输出Top10 // @author YourName // @match https://www.youtube.com/watch* // @grant none // @run-at document-idle // ==/UserScript== (function() { 'use strict'; // 等待评论加载完成(需根据实际页面结构调整) const waitForComments = () => { return new Promise((resolve) => { const observer = new MutationObserver(() => { const comments = document.querySelectorAll('#content-text'); // 评论元素选择器 if (comments.length > 0) { observer.disconnect(); resolve(comments); } }); observer.observe(document.body, { childList: true, subtree: true }); }); }; // 统计词频 const analyzeWordFrequency = (texts, stopWords = ['的', '是', '在', '了']) => { const wordMap = {}; texts.forEach(text => { text.trim() .toLowerCase() .replace(/[^\w\s]/g, '') // 去标点 .split(/\s+/) .filter(word => word.length > 1 && !stopWords.includes(word)) .forEach(word => { wordMap[word] = (wordMap[word] || 0) + 1; }); }); return Object.entries(wordMap).sort((a, b) => b[1] - a[1]); }; // 主逻辑 const main = async () => { try { const comments = await waitForComments(); const commentTexts = Array.from(comments).map(c => c.textContent); const topWords = analyzeWordFrequency(commentTexts).slice(0, 10); console.log('【Top10高频词】'); topWords.forEach(([word, count], index) => { console.log(`${index + 1}. ${word}: ${count}次`); }); } catch (error) { console.error('脚本执行失败:', error); } }; // 延迟启动以避免干扰页面加载 setTimeout(main, 3000); })();这段代码只爬了前两句评论,但实际有上千条评论,请完善这个问题
03-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值