先说需求,根据数组中的ID值,对每个ID发送请求,获取数据进行操作。

首先肯定考虑用forEach 或者 map对数组进行遍历,然后根据值进行操作,但是请求是个异步操作,forEach又是一个同步操作,等同于同时发出多个异步请求,并不能确定具体返回的数据是哪个请求。(我这里的返回数据中有ID值,可以根据ID查找,这不就是太low了嘛,每次拿到返回来的数据,还得遍历一遍原数组才行)

那么我们如何才能做到即遍历数组又发送请求,同时根据返回值进行操作呐。

解释几点:(不想看的人直接跳结果)

async函数:返回一个promise对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到触发的异步操作完成,再接着执行函数体后面的语句。

await会获取promise的成功回调resolve()返回值,并且只能使用在async函数中(这表面这个函数中有异步操作)同时await将异步变成同步,增加了代码逻辑可读性。注意一点,既然是异步promise就有可能会有rejected的结果,所以一般使用try···catch···或者.catch 来处理请求出错

结果:

当需要同时发起多个异步,可以使用promise.all

// const aa = this.testNumArray.map((item) => {

// return this.getFetch(item);

// });

// const bb = Promise.all(aa);

// bb.then((val) => {

// console.log(val, 'bb-result');

// });

这里的getFetch就是发送的异步请求;

如果后一步的异步请求需要依赖于前一步的数据,即当一个异步请求完结后拿到数据才可以继续发送下一个请求,可以将for of和async/await结合使用

foo = async (array: any) => {

for (let i of array) {

const item = await this.getFetch(i);

console.log(item);

}

};

注意await这里等到的值,一定是一个promise对象(虽然他也可以处理非promise对象,同样可以作为resolve()的值进行输出)

这里解释一下,为何forEach是没有作用的,forEach的第一个参数是一个函数,他的源码中并没有对可遍历对象的异步进行处理,所以他是一个即时操作的回调函数,并不能达到我们异步的需求。

参考网址https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#polyfill

源码:

// Production steps of ECMA-262, Edition 5, 15.4.4.18

// Reference: http://es5.github.io/#x15.4.4.18

if (!Array.prototype.forEach) {

Array.prototype.forEach = function(callback, thisArg) {

var T, k;

if (this == null) {
throw new TypeError(' this is null or not defined');
} // 1. Let O be the result of calling toObject() passing the
// |this| value as the argument.
var O = Object(this); // 2. Let lenValue be the result of calling the Get() internal
// method of O with the argument "length".
// 3. Let len be toUint32(lenValue).
var len = O.length >>> 0; // 4. If isCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if (typeof callback !== "function") {
throw new TypeError(callback + ' is not a function');
} // 5. If thisArg was supplied, let T be thisArg; else let
// T be undefined.
if (arguments.length > 1) {
T = thisArg;
} // 6. Let k be 0
k = 0; // 7. Repeat, while k < len
while (k < len) { var kValue; // a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty
// internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) { // i. Let kValue be the result of calling the Get internal
// method of O with argument Pk.
kValue = O[k]; // ii. Call the Call internal method of callback with T as
// the this value and argument list containing kValue, k, and O.
callback.call(T, kValue, k, O);
}
// d. Increase k by 1.
k++;
}
// 8. return undefined

};

}

这里看不懂没有关系,记住一点,红色的代码就是直接执行回调函数。

同时,人家官方都说了:如果使用 promise 或 async 函数作为 forEach() 等类似方法的 callback 参数,最好对造成的执行顺序影响多加考虑,否则容易出现错误

let ratings = [5, 4, 5];

let sum = 0;

let sumFunction = async function (a, b) {

return a + b;

}

ratings.forEach(async function(rating) {

sum = await sumFunction(sum, rating);

})

console.log(sum);

// Expected output: 14

// Actual output: 0

那么问题来了,既然forEach不行,那么for ··· of 为何可以呐?难道for ··· of比较牛逼嘛?

那话如果这么说,for ··· of真滴比较牛逼,因为for循环内置的是一个迭代器,通过Symbol.iterator对可迭代对象的循环。

这里就有一个面试常问到的地方,就是for···of和for···in有什么区别?

当然是遍历的值不同了(of:键值对,in:key值),还有原理实现上的不同,for···of只能对可迭代对象进行遍历循环。for···of可以视为一个迭代器,那么他也有迭代器能终止迭代的属性(break throw continue return)

注意:

  1. 在es6中Object是被认为不可迭代的对象,不能用for···of来循环。
  2. for ···in会遍历所操作对象的所有可枚举属性,包括原型上的属性和方法。

关于在forEach中使用await的问题的更多相关文章

  1. 聊一聊C# 8.0中的await foreach

    AsyncStreamsInCShaper8.0 很开心今天能与大家一起聊聊C# 8.0中的新特性-Async Streams,一般人通常看到这个词表情是这样. 简单说,其实就是C# 8.0中支持aw ...

  2. C#8.0中的 await foreach

    AsyncStreamsInCShaper 8.0 C# 8.0中支持异步返回枚举类型async Task<IEnumerable<T>> sync Streams这个功能已经 ...

  3. C#中async/await中的异常处理

    在同步编程中,一旦出现错误就会抛出异常,我们可以使用try-catch来捕捉异常,而未被捕获的异常则会不断向上传递,形成一个简单而统一的错误处理机制.不过对于异步编程来说,异常处理一直是件麻烦的事情, ...

  4. 关于C#中async/await中的异常处理(下)-(转载)

    上一篇文章里我们讨论了某些async/await的用法中出现遗漏异常的情况,并且谈到该如何使用WhenAll辅助方法来避免这种情况.WhenAll辅助方法将会汇总一系列的任务对象,一旦其中某个出错,则 ...

  5. 小心C# 5.0 中的await and async模式造成的死锁

    平时在使用C# 5.0中的await and async关键字的时候总是没注意,直到今天在调试一个ASP.NET项目时,发现在调用一个声明为async的方法后,程序老是莫名其妙的被卡住,就算声明为as ...

  6. C#实现在foreach中删除集合中的元素

    List<string> str = new List<string>(); str.Add( "zs"); str.Add("ls") ...

  7. C# 6.0:在catch和finally中使用await

    Asyn方法是一个现在很常用的方法,当使用async和await时,你或许曾有这样的经历,就是你想要在catch块或finally块中使用它们,比如当出现一个exception而你希望将日志记在文件或 ...

  8. php在foreach中使用引用赋值&可能遇到的问题(转)

    楼主在写项目的时候,由于初涉PHP的赋值引用操作,觉得这个功能非常强大,用时一时爽,没有深入了解过其中的原理,导致了一些当时觉得不可思议的BUG,废话不都说,我举个例子详细的描述一下这个问题. 代码: ...

  9. 关于C#中async/await中的异常处理(上)-(转载)

    在同步编程中,一旦出现错误就会抛出异常,我们可以使用try…catch来捕捉异常,而未被捕获的异常则会不断向上传递,形成一个简单而统一的错误处理机制.不过对于异步编程来说,异常处理一直是件麻烦的事情, ...

随机推荐

  1. CORS OPTIONS

    CORS OPTIONS A CORS preflight request is a CORS request that checks to see if the CORS protocol is u ...

  2. 教你吃透CSS的盒子模型(Box Model)

    CSS 盒子模型(Box Model) 所有HTML元素可以看作盒子,在CSS中,"box model"这一术语是用来设计和布局时使用. CSS盒模型本质上是一个盒子,封装周围的H ...

  3. 能取值亦能赋值的Python切片

    切片,就像面包,给几刀,切成一片一片,可以做成吐司,也可以做成三明治,口味更佳: 列表(list).元组(tuple).字符串(str)都能进行切片,得到子片段,实际上切片操作比想象的要强大很多,能取 ...

  4. 零信任三大技术之SDP

    SDP概述 SDP Software Defined Perimeter(软件定义边界),2013 年由云安全联盟 CSA提出. SDP 设计基本原则 1.信息隐身:隐藏服务器地址.端口,使之不被扫描 ...

  5. 下载HLS视频到本地

    现在绝大多数网站播放视频都采用HLS技术,像腾讯优酷爱奇艺等等.本篇博文将介绍如何下载这样的视频到本地. 前言 因疫情影响,上课部分课程采用腾讯课堂上课,腾讯课堂有直播回放功能,但这个功能腾讯显然没有 ...

  6. HBase 数据存储结构

    在HBase中, 从逻辑上来讲数据大概就长这样: 单从图中的逻辑模型来看, HBase 和 MySQL 的区别就是: 将不同的列归属与同一个列族下 支持多版本数据 这看着感觉也没有那么太大的区别呀, ...

  7. MongoDB 在Node中的应用

    转: MongoDB 在Node中的应用 文章目录 一 .什么是 MongoDB? 二.小Demo 三.Demo 增删改查 3.1 新增 3.2 查询 3.2.1 查询所有 [{},{}] 找不到返回 ...

  8. C#正则实现匹配一块代码段

    最近项目,生成聚合网关,但是生成的网关文件中,存在着不必要的代码段,比如一个类A,类B等 之前一直使用手动删除,这么做劳民伤财,浪费时间,考虑使用正则写一个工具实现自动删除. 正则写法: string ...

  9. Mybatis系列全解(六):Mybatis最硬核的API你知道几个?

    封面:洛小汐 作者:潘潘 2020 年的大疫情,把世界撕成几片. 时至今日,依旧人心惶惶. 很庆幸,身处这安稳国, 兼得一份安稳工. · 东家常讲的一个词:深秋心态 . 大势时,不跟风.起哄, 萧条时 ...

  10. JS动态获取select中被选中的option的值,并在控制台输出

    生活城市: <select id="province"> <option>河南省</option> <option>黑龙江省< ...