如何在node.js中使用ES7的nodejs async foreach函数

Nodejs 中使用 Async/Await - 简书
Nodejs 中使用 Async/Await
从一个讨论开始,
async function rejectionWithReturnAwait () {
return await Promise.reject(new Error());
} catch (e) {
return 'Saved!';
async function rejectionWithReturn () {
return Promise.reject(new Error());
} catch (e) {
return 'Saved!';
上面的代码几乎相同,只是第一段中在Promise函数前有一个await关键字,但是两段代码的运行效果确实千差万别。想要了解其中缘由,且听我娓娓道来。
1. Nodejs想说爱你不容易
Node.js(R) is a JavaScript runtime built on . Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, , is the largest ecosystem of open source libraries in the world.
基于Javascript的语法、非阻塞单线程的特性,使得nodejs在处理I/O时非常麻烦。破解之道依次经历过callback瀑布级回调嵌套、Promises函数、Generator函数 详细参见我的另外一篇学习笔记。
尽管社区和ECMA管委会不断提出解决异步的方案,但是仍不能满足神经质的开发人员对清洁代码矢志不渝追求。直至在ES7中async函数的出现,很快Nodejs社区也在7.6版本中添加了async函数,至此Nodejs无缝链接async函数,Nodejs异步的难题才算是取得了里程碑式的进展。
2. 偷窥Async函数
先从一段代码开始:
// await 关键字后的函数
var Delay_Time = function(ms) {
return new Promise(function(resolve) {
setTimeout(resolve, 1000)
// async 函数
var Delay_Print = async function(ms) {
await Delay_Time(ms)
return new Promise(function(resolve, reject) {
resolve("End");
// 执行async函数后
Delay_Print(1000).then(function(resolve) {
console.log(resolve);
上面的示例代码定义了三个方法块,分别是async 声明的函数体、await 执行的函数体、async 函数执行后的函数体。整段代码执行的结果是在1000毫秒后,控制台打印出“End”。
通过整段代码我们可以看出:
a. 在函数体前通过关键字async可以将函数变为async函数
b. 在async函数中对需要异步执行的函数前需加await关键字
c. await后的函数必须使用Promise对象封装
d. async函数执行后返回的是一个Promise对象
3. async与await这对大宝贝
Promise对象状态的变化
var delay_print_first = function() {
return "First";
var delay_print_second = function() {
return Promise.resolve("Second");
var delay_print_third = function() {
return Promise.resolve("Third");
var async_status = async function(ms) {
var first = await delay_print_first();
var send = await delay_print_second();
var third = await delay_print_third();
return first + " " + send + " " +
async_status().then((ret)=& {
console.log(ret); // First Second Third
async函数必须要等到方法体中所有的await声明Promise函数执行完后,async函数才会得到一个resolve状态的Promise对象。
如果在执行async中的异步函数的过程中,一旦有一个异步函数出现错误,整个async函数就会立即抛出错误,但是如果在async函数中对异步函数通过try/ catch封装,并在catch方法体中返回Promise.reject(),这样async函数将得到一个reject状态的Promise,有效的避免因为异步函数导致整个async函数的终止。
为了有效的记录下error的信息,通常会在async执行后做一些Promise catch的处理。 如下面的代码:
var delay_print_first = function() {
return "First";
var delay_print_second = function() {
return Promise.resolve("Second");
var delay_print_third = function() {
return Promise.reject("Third");
var async_status = async function(ms) {
var first =
await delay_print_first();
var send = await delay_print_second();
var third = await delay_print_third();
return first + " " + send + " " +
} catch (error) {
return Promise.reject("Some error")
async_status().then((ret)=& {
console.log(ret);
}).catch((err) =& {
console.log(err);
// Some error
await关键字的作用
async中的函数如果不使用await声明就是普通函数
var Delay_Time = function(ms) {
return new Promise(function(resolve) {
setTimeout(resolve, ms)
var Delay_Time_Second = function (ms) {
setTimeout(function() {
var Delay_Print = async function(ms) {
Delay_Time_Second(2000);
console.log("After Delay_Time_Second")
await Delay_Time(ms)
console.log("After Delay_Time")
return new Promise(function(resolve, reject) {
resolve("END");
Delay_Print(2000).then(function(resolve) {
console.log(resolve);
上面的代码的执行结果是:
a. 立即打印出"After Delay_Time_Second"
b. 过了2000毫秒后打印出 "After Delay_Time"
c. 最后打印出"END"
在正常的情况下,await后是一个Promise对象。如果不是就会立马转换成一个立即resolve的Promise对象。
var await_fun = async function() {
return await "END";
await_fun().then((ret) =& {
console.log(ret);
上面代码中async的方法体,相当于下面
var await_fun = async function() {
return Promise.resolve('END');
多个函数并发执行
如果async中的多个函数是在执行的先后没有要求,最好把多个函数变为并发执行。
async function dbFuc(db) {
let docs = [{}, {}, {}];
let promises = docs.map((doc) =& db.post(doc));
let results = await Promise.all(promises);
console.log(results);
如果async函数体中有多个await 声明的函数,且await 之间是并发的,await声明的函数体是继发的,见如下代码:
var delay_time = function(ms, param) {
return new Promise(function(resolve) {
setTimeout(function() {
console.log(new Date().getTime());
resolve(param);
var asyn_fun = async function (params) {
var time_out = 1000;
const results = await params.map(async param =& {
time_out = time_out + 1000;
await delay_time(time_out, param);
return out
var target = [];
for(var ret of results) {
target.push(await ret);
asyn_fun(['First','Second','Third','Last']).then(function(result){
console.log(JSON.stringify(result))
// ["First","Second","Third","Last"]
虽然map方法的参数是async函数,但它是并发执行的,因为只有async函数内部是继发执行,外部不受影响。后面的for..of循环内部使用了await,因此实现了按顺序输出。
4. 最后回到开篇的问题
async function rejectionWithReturnAwait () {
return await Promise.reject(new Error());
} catch (e) {
return 'Saved!';
rejectionWithReturnAwait().then((ret) =& {
console.log(ret);
// "Saved"
这段代码在async方法体中通过try/catch捕获被await声明并且状态是rejected的Promise对象,捕获异常后返回立即执行的Promise对象。
async function rejectionWithReturn () {
return Promise.reject(new Error());
} catch (e) {
return 'Saved!';
rejectionWithReturn().then((ret) = & {
console.log(ret);
上面async代码快内的Promise对象没有使用await关键字声明,因为当Promise对象的状态由pending变成rejected后并不能try/catch捕获,代码的执行结果如下:
(node:50237) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 5): Error
(node:50237) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
stay hungry, stay foolish.
异步编程对JavaScript语言太重要。Javascript语言的执行环境是“单线程”的,如果没有异步编程,根本没法用,非卡死不可。 ES6诞生以前,异步编程的方法,大概有下面四种。 回调函数 事件监听 发布/订阅 Promise 对象 ES6将JavaScript异步编...
[注:以下代码都在支持 Promise 的 Node 环境中实现] 1 promise 释义 promise 是抽象异步处理的对象,其提供了一系列处理异步操作的方法。 1.1 语法 例子1-1: 1.2 static method 像 Promise 这样的全局对象还拥有一...
JavaScript Promise 迷你书(中文版) 超详细介绍promise的gitbook,看完再不会promise...... 本书的目的是以目前还在制定中的ECMAScript 6 Promises规范为中心,着重向各位读者介绍JavaScript中对Promis...
pdf下载地址:Java面试宝典 第一章内容介绍 20 第二章JavaSE基础 21 一、Java面向对象 21 1. 面向对象都有哪些特性以及你对这些特性的理解 21 2. 访问权限修饰符public、private、protected, 以及不写(默认)时的区别(201...
本文首发在个人博客:http://muyunyun.cn/posts/7b9fdc87/ 提到 Node.js, 我们脑海就会浮现异步、非阻塞、单线程等关键词,进一步我们还会想到 buffer、模块机制、事件循环、进程、V8、libuv 等知识点。本文起初旨在理顺 Node...
刚看到朋友发的那女的照片,我又开始胡思乱想了,又开始各种不自信,想对方是在挑衅我。最后我想了一下,我的世界我做主,干嘛去为一些不相干的人伤神呢,为什么不好好把自己的生活过好,把游戏玩好呢!我有能力把搞砸,也有能力让他好起来,耶耶耶!
前段时间因为看了《断舍离》所以一直打算要好好的收拾家里一番,在收拾的过程中就相当于是给自己的心灵腾出更多的空间。
去年我出去旅行的时候无意间翻了一本杂志,是关于心理学的。在心理学中整理物品确实是可以给自己心灵减压的最好方式。
有一句话是这样说的,当你觉得生气的时...
两年前,曾经写到: “有时候在深夜,坐在出租车内,北京的深夜是美的,它终于透漏出一点慵懒或者是漫不经心。当我从桥下经过,看着桥上的火车呼啸而过,看着身边断续的车流擦肩而过,我看着这些行驶的一切,看着他们,像穿越时空一般,也许火车上的某个有光的窗子有个人也在盯着桥下的车流,而...
见过你 冬天是热的,夏天是凉的 见过你 风是轻的云是软的空气是甜甜的 见过你 时间是静止的空间是相通的宇宙是迷你的 见过你
是的我回来了。 生活真是滑稽非常。 但兜兜转转,还不是一如既往。 昨晚,和四四去了卢思浩的图书分享会,得到了现场签名,我的名字和作者的名字,种种,都是人生中第一次。 卢思浩说,要跟这世界战斗到底。 他还说,希望很久之后能看到你们其中一个写的书,到你们的签售会上,静静地听你们...node异步编程async/await/promise - 简书
node异步编程async/await/promise
最近在用node写一个小爬虫学习node,但是遇到一个不大不小的坑,就是如何将异步的node程序串行执行。下面就我遇到的坑和解决方法简单记录一下。
1.问题介绍
首先,我想通过request去访问小木虫网站,获得文章的列表,首先写了一个getList函数:
var request = require('request');
var iconv = require('iconv-lite');
const urlStart = "http://muchong.com/bbs/journal_cn.php?tag=%BC%C6%CB%E3%BB%FA%D3%A6%D3%C3%BC%BC%CA%F5"
const regExp = /&th\s+&\s+&a\s+href="(.{30,40})"&(.{4,20})&\/a&/
function getList() {
console.log('start get list ...');
var link_array = [];
// request visit muchong.com
url: urlStart,
encoding: null
}, function (err, res, body) {
if (err) {
console.log('getList err:' + err);
var html = iconv.decode(body, 'GBK');
while ((regRes = regExp.exec(html)) !== null) {
link_array.push({
link: regRes[1],
name: regRes[2]
console.log(link_array);
return link_
exports.getList = getL
整个代码如上,简单的对结果进行了正则,返回一个文章列表,给外部暴露getList()这个函数。然后我再通过文件index.js调用该模块:
var getList = require('./src/getList');
(function(){
const temp_array = getList.getList();
console.log('temp_array is:'+JSON.stringify(temp_array));
然后执行该程序,结果返回temp_array is:undefined。跟预想的结果不同。
2.问题分析
单独调试getList结果正常,那么问题应该就是index.js出问题了。很快我就发现,这里一定是因为getList()没有执行完毕,就调用下一句console.log了,因此需要程序等待getList()。网上查资料,发现可以通过async/await完成该功能,于是我就修改index.js为:
var getList = require('./src/getList');
(async function(){
const temp_array = await getList.getList();
console.log('temp_array is:'+JSON.stringify(temp_array));
So easy!加个类似修饰器之类的async/await就可以啦,再执行,结果还是undefined。这又是为何呢?为了解决问题,继续google,通过查询API和用法才知道,node的异步API都是通过一个叫Promise的东东封装成异步函数的,await的操作对象也应该是Promise对象,否则会马上返回。因此我们需要重新修改getList,使用Promise来封装:
var request = require('request');
var iconv = require('iconv-lite');
const urlStart = "http://muchong.com/bbs/journal_cn.php?tag=%BC%C6%CB%E3%BB%FA%D3%A6%D3%C3%BC%BC%CA%F5"
const regExp = /&th\s+&\s+&a\s+href="(.{30,40})"&(.{4,20})&\/a&/
async function getList() {
return new Promise(function(resolve, reject){
console.log('start get list...');
var link_array = [];
url:urlStart,
encoding: null
}, function(err, res, body){
console.log('getList err:'+err);
reject(err);
var html = iconv.decode(body, 'GBK');
while((regRes = regExp.exec(html)) !==null){
link_array.push({
link:regRes[1],
name:regRes[2]
console.log('Get list OK..');
resolve(link_array);
exports.getList = getL
上面getList返回的是一个Promise对象,这样await就会等待Promise返回值,而Promise通过resolve(成功时)和reject(失败时)这两个参数传递数据。
再次执行index.js得到正常的结果。值得注意的是,必须使用node7.1以后的版本才能使用async/await,另外await必须在async修饰的函数内使用,多一层嵌套都不能使用await(除非嵌套的函数也是async修饰)这是我练习时踩的坑!都是泪
请叫我软件工程师,而不是码农...哈哈哈
异步编程对JavaScript语言太重要。Javascript语言的执行环境是“单线程”的,如果没有异步编程,根本没法用,非卡死不可。 ES6诞生以前,异步编程的方法,大概有下面四种。 回调函数 事件监听 发布/订阅 Promise 对象 ES6将JavaScript异步编...
本文首发在个人博客:http://muyunyun.cn/posts/7b9fdc87/ 提到 Node.js, 我们脑海就会浮现异步、非阻塞、单线程等关键词,进一步我们还会想到 buffer、模块机制、事件循环、进程、V8、libuv 等知识点。本文起初旨在理顺 Node...
一.非阻塞和异步 借用知乎用户严肃的回答在此总结下,同步和异步是针对消息通信机制,同步代表一个client发出一个调用,不管是远程调用还是本地调用,在没有得到结果之前就不返回,一直等到调用返回,就得到返回值了。而异步调用恰恰相反,调用在发出之后,就直接返回了,没有返回结果。...
javascript的运行机制是单线程处理,即只有上一个任务完成后,才会执行下一个任务,这种机制也被称为“同步”。 “同步”的最大缺点,就是如果某一任务运行时间较长,其后的任务就无法执行。这样会阻塞页面的渲染,导致页面加载错误或是浏览器不响应进入假死状态。 如果这段任务采用...
前言 对于Node.js的异步控制流,目前共计有四种常用的方式。较为经典的为callback和EventEmitter;在ES6中,加入了Promise;在ES7中加入了async/await。下面就逐个分析一下这四种常用的异步控制。 callback形式的异步控制 对于c...
学校文化建设纲要(提纲草案) 序 (字数约200—300) 第一部分 概述 (字数约) 一、学校的基本情况 学校的现状及其简介 获得的主要荣誉 发展前景 二、文化建设的定位 指导思想 基本目标 实施原则 工作策略 第二部分 思想系统 (字数约2000—40...
最近加了一个写手群,发现大家经常在群里问一个问题:“我也想每天码字,但每天不知道写什么?” “不知道写什么”这是很多新手写作者都会遇到的问题,甚至有一部分新手就直接夭折在这个环节了。 我也是新手写作者,坚持写了两个多月,从最初每天写800字,到现在一天可以写两篇2000字的...
这部迪士尼动画是因为女儿,看了数不清多少遍,但每次女儿还是喜欢看,我依然会陪着看。 女儿喜欢里面的姐姐,每次出去看到比她大的姐姐就上前拉着别人手,在她的心里,姐姐都是很厉害,会魔法的。 慢慢的几遍看过后,女儿开始关注里面的雪人,生活在南方的宝贝,没有见过雪人,更不理解雪宝对...
by Denny 今天我终于找到了我的人生意义,找到了一件我愿意用尽一生时间、所有才华和智力去做的事,而不再仅仅是平凡地过日子。我的梦想曾经是未来有一天能与外星人实现一次交流(于我个人而言,我不在乎其安不安全,但我必定会考虑全人类利益),而现在我发现对于宇宙的探索,人类已经...
混乱的时局,人性的自由。将魏晋南北朝的“乱”字抛开一边,用大量笔墨来介绍魏晋时期的文化。从另一个角度上说明这个时代留给后世的文化遗产。只是,这些这本书不算是小说类,有点普及历史的意思。真对这段历史有兴趣的话,可以作为入门看一看。 看完王小波先生的这部作品,我总感觉自己有些人...主题信息(必填)
主题描述(最多限制在50个字符)
申请人信息(必填)
申请信息已提交审核,请注意查收邮件,我们会尽快给您反馈。
如有疑问,请联系
CSDN &《程序员》研发主编,投稿&纠错等事宜请致邮
你只管努力,剩下的交给时光!
如今的编程是一场程序员和上帝的竞赛,程序员要开发出更大更好、傻瓜都会用到软件。而上帝在努力创造出更大更傻的傻瓜。目前为止,上帝是赢的。个人网站:www.xttblog.com。个人QQ群:、
个人大数据技术博客:http://www.iteblog.com匿名用户不能发表回复!|

我要回帖

更多关于 nodejs async await 的文章

 

随机推荐