node 异步编程

我了解到的node异步编程可分成: 
1.回调函数 
2.pub/sub模式(发布/订阅模式) 
3.promise 
4.generator 
5.async await

一.直接回调函数

该方法是最直接常用的异步操作方式,比如在setInterval 和 ajax等会使用到, 存在缺点有: 
1.代码不易阅读并且容易出现金字塔嵌套问题; 
2.一般只能对应一个回调函数(一对一),使用上有一定的限制;

fs.readFile('/etc/passwd', function (err, data) {
if (err) throw err;
console.log(data);
});

函数先读取/etc/passwd,再执行回调函数,在这两者之间抛出的错误会以参数形式传入回调函数中。

二.发布/订阅模式

该方法不再局限于一对一的形式,以多对多的形式监听事件,可以很方便的订阅和取消订阅存在缺点有:需要借助类库(jQuery),事件与回调函数的顺序很重要。

三. Promise

回调函数的缺点之一是容易出现函数多层嵌套,难以维护的场面.而es6语法中的promise正好解决这类问题. Promise包含三种状态:pending、fulfilled、rejected,三种状态只能发生两种转换(从pending—>fulfilled、pending—>rejected),并且状态的转换仅能发生一次。 
Promise实例生成以后,可以用then方法分别指定Resolved状态和Reject状态的回调函数: 
then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为Resolved时调用,第二个回调函数是Promise对象的状态变为Reject时调用。 
a) then方法返回Promise。这样就实现了多个异步操作的串行操作。 
b)实现了多个不同异步库之间的转换。

var p1 = new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('fail')), 3000)
})
var p2 = new Promise(function (resolve, reject) {
setTimeout(() => resolve(p1), 1000)
})
p2.then(result => console.log(result))
p2.catch(error => console.log(error))
// Error: fail
Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例。是我们项目中正在使用的方式。如var p = Promise.all([p1,p2,p3]);p的状态由p1、p2、p3决定,分成两种情况。

(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。

(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

四.Generator

Generator最大的特点就是可以实现函数的暂停、重启,这个特性非常有利于解决异步操作有两个名词需要注意yield 和 next。

  1. generator的解决机制有点像线程.next方法的作用是分阶段执行Generator函数。每次调用next方法,会返回一个对象,表示当前阶段的信息(value属性和done属性)。value属性是yield语句后面表达式的值,表示当前阶段的值;done属性是一个布尔值,表示Generator函数是否执行完毕,即是否还有下一个阶段。
  2. yield 命令是标志异步操作的标志,如果去掉此命令,函数就会像执行同步函数那样执行就暂停,等到执行权返回,再从暂停的地方继续往后执行。 
    Generator 函数的还提供了数据交换和错误处理机制。其函数内部还可以部署错误处理代码,捕获函数体外抛出的错误。
function* gen(x){
try {
var y = yield x + 2;
} catch (e){
console.log(e);
}
return y;
} var g = gen(1);
g.next();
g.throw('出错了');
// 出错了
除此之外,generator函数还有两个小帮手Thunk函数(自动控制Generator函数的流程,接收和交还程序的执行权的一种机制)和co模块(用于Generator函数的自动执行。)

五.async await

ES7提供了async函数,成为generator函数的语法糖,它主要就是用async来说代替*,用await来代替yield,除此之外,他还带来了一些便利之处: 
1.generator函数的调用需要借助next方法或者是co模块,而async和普通函数的调用一样,不需要借助任何函数; 
2.co模块约定,yield命令后面只能是Thunk函数或Promise对象,而async函数的await命令后面,可以是Promise对象和原始类型的值 
注意的是: await 命令只能用在 async 函数之中,如果用在普通函数,就会报错。

async function dbFuc(db) {
let docs = [{}, {}, {}]; // 报错
docs.forEach(function (doc) {
await db.post(doc);
});
}

上面代码会报错,因为 await 用在普通函数之中了。但是,如果将 forEach 方法的参数改成 async 函数,也有问题。

async function dbFuc(db) {
let docs = [{}, {}, {}]; // 可能得到错误结果
docs.forEach(async function (doc) {
await db.post(doc);
});
}
上面代码可能不会正常工作,原因是这时三个 db.post 操作将是并发执行,也就是同时执行,而不是继发执行。正确的写法是采用 for 循环。
async function dbFuc(db) {
let docs = [{}, {}, {}]; for (let doc of docs) {
await db.post(doc);
}
}

如果确实希望多个请求并发执行,可以使用 Promise.all 方法。

async function dbFuc(db) {
let docs = [{}, {}, {}];
let promises = docs.map((doc) => db.post(doc)); let results = await Promise.all(promises);
console.log(results);
} // 或者使用下面的写法 async function dbFuc(db) {
let docs = [{}, {}, {}];
let promises = docs.map((doc) => db.post(doc)); let results = [];
for (let promise of promises) {
results.push(await promise);
}
console.log(results);
}
内容涉及的不是很深入,后续会继续补充和修改,希望大家多多指正

node 异步编程的更多相关文章

  1. Node.js之异步编程

    > 文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. ![file](https://img2018.cnblogs.com/blog/830272/20 ...

  2. 《深入浅出Node.js》第4章 异步编程

    @by Ruth92(转载请注明出处) 第4章 异步编程 Node 能够迅速成功并流行起来的原因: V8 和 异步 I/O 在性能上带来的提升: 前后端 JavaScript 编程风格一致 一.函数式 ...

  3. 深入浅出node(4) 异步编程

    一)函数式编程基础 二)异步编程的优势和难点 2.1 优势 2.2 难点 2.2.1 异常处理 2.2.2 函数嵌套过深 2.2.3 阻塞 2.2.4 多线程编程 2.2.5 异步转同步 三)异步编程 ...

  4. node.js异步编程的几种模式

    Node.js异步编程的几种模式 以读取文件为例: 1.callback function const fs = require('fs'); //callback function fs.readF ...

  5. 深入理解node.js异步编程:基础篇

    ###[本文是基础内容,大神请绕道,才疏学浅,难免纰漏,请各位轻喷] ##1. 概述 目前开源社区最火热的技术当属Node.js莫属了,作为使用Javascript为主要开发语言的服务器端编程技术和平 ...

  6. Node单线程与异步编程的初步理解

    最近学习了一些关于node的单线程与异步的知识,想拿过来和大家分享下: var async = require('async') //并行无关联,等待事件为最长时间请求过程.如以下两个任务执行时间 c ...

  7. node.js异步编程解决方案之Promise用法

    node.js异步编程解决方案之Promise var dbBase = require('../db/db_base'); var school_info_db = require('../db/s ...

  8. Node.js学习笔记(2)——关于异步编程风格

    Node.js的异步编程风格是它的一大特点,在代码中就是体现在回调中. 首先是代码的顺序执行: function heavyCompute(n, callback) { var count = 0, ...

  9. 17.Node.js 回调函数--异步编程

    转自:http://www.runoob.com/nodejs/nodejs-tutorial.html Node.js 异步编程的直接体现就是回调. 异步编程依托于回调来实现,但不能说使用了回调后程 ...

随机推荐

  1. 妙味课堂——HTML+CSS基础笔记

    妙味课堂的课程讲得非常的清楚,受益匪浅.先把HTML和CSS基础课程部分视频的学习笔记记录如下: padding #PS基础 ##前端需要的PS技能 - PS技能(前端需要):切图.修图.测量 - P ...

  2. java任务调度quartz框架的小例子

    quartz是一个开源的作业调度框架,当然,java可以使用Timer来实现简单任务调度的功能,但Timer是单线程的设计方案,使得一个任务延迟会影响到其他的任务.java也可以使用Scheduled ...

  3. <四>JDBC_PreparedStatement的使用

    WHY? <1>使用Statement需要进行拼写SQL语句,容易出错; <2>PreparedStatement:是Statement的子接口,可以传入带占位符的SQL语句, ...

  4. 客户端JavaScript-如何执行

    客户端JavaScript程序有四部分:内联脚本.HTML事件处理程序.URL中的JavaScript.外联脚本:所有这些单独的代码共用同一个全局Window对象,它们可以看到相同的Document对 ...

  5. 【iCore3 双核心板_FPGA】实验二十六:SDRAM读写测试实验

    实验指导书及代码包下载: http://pan.baidu.com/s/1c1VRibY iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...

  6. 不断优化,重构我的代码-----拖拽jquery插件

    最近学东西学的有点太散了,歇一阵子,重新完善之前的JQ插件,今天先上拖拽吧 // JavaScript Document (function($){ var defaults = { actionEl ...

  7. 骑士游历/knight tour - visual basic 解决

    在visual baisc 6 how to program 中文版第七章的练习题上看到了这个问题,骑士游历的问题. 在8x8的国际象棋的棋盘上,骑士(走法:一个方向走两格,另一个方向一格)不重复走完 ...

  8. 对接第三方支付接口-获取http中的返回参数

    这几天对接第三方支付接口,在回调通知里获取返回参数,有一家返回的json格式,请求参数可以从标准输入流中获取. //1.解析参数 , 读取请求内容 BufferedReader br; String ...

  9. MVC原理

       C代表Controller,负责用户界面和业务逻辑层的通信控制,一方面解释来自用户界面的输入,识别用户动作(如点击按钮等),调用相应Model中的方法, 另一方面处理来自Model的事件和返回的 ...

  10. java classpath getResource getResourceAsStream

    1.classpath 用于指定java运行时,jvm寻找class文件以及jar文件的存储目录.jvm依据classpath中出现的jar文件以及目录,依次寻找,直到找到指定class文件. 例:j ...