博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
异步编程方案进化论
阅读量:6119 次
发布时间:2019-06-21

本文共 3018 字,大约阅读时间需要 10 分钟。

异步方案进化过程: callback ---> promise ---> generator + co ---> async + await 本文以nodejs中最常用的文件异步读取操作readFile为例,来说明各个方案下的实现方式。

前提

假设我们现在有两个文件1.txt和2.txt,1.txt的内容是'./2.txt'(2的路径),2.txt的内容是'异步,又见异步'。

需求1

拿到1的内容作为路径去读取2的内容打印出来。

需求2

同时读取两个文件,在两个文件都读取完成时,将文件中的内容合并。

callback

需求1实现

fs.readFileSync('./1.txt', 'utf8', function(err, data) {    if(err) { throw err; }    fs.readFileSync(data, 'utf8', function(err, data) {        if(err) { throw err; }        console.log(data);    })})复制代码

此时我们很容易利用了回调嵌套,嵌套多了就容易累积出回调地狱。

需求2实现

这个需求实现我们先需要了解一个lodash的_after函数

_after函数

_after函数返回一个函数,在这个函数调用次数达到一定限度时,调用回调函数。下面写一个自己的after函数:

function after(times, callback) {    return function() {        if(--times === 0) {            callback();        }    };}let sleep = after(3, function() {    console.log('睡饱了');});sleep();sleep();sleep();//打印出睡饱了复制代码

写一个afterRead函数来得到一个read函数,如下:

function afterRead(times, callbacks) {    let arr = [];    return function(path) {        fs.readFile(path, 'utf8', function(err, data) {            if(err) { throw err; }            arr.push(data);            if(--times === 0) {                callbacks(arr);            }        });    }}let read = afterRead(2, function(dataArr) {    console.log(dataArr);});read('./1.txt');read('./2.txt');//读完第二个文件打印出['./2.txt', '异步,又见异步']复制代码

Promise

需求1实现

function read(path) {    return new Promise(function(resolve, reject) {        fs.readFile(path, 'utf8', function(err, data) {            if(err) { reject(err); }            resolve(data);        });    });}read('./1.txt').then(function(data) {    return read(data);//将产生的promise返回出去进行下一步处理}, function(err) {    console.log(err);}).then(function(data) {    console.log(data);});复制代码

需求2实现

使用Promise.all(),能够方便进行处理,并且返回的数据是按照请求发起的顺序存放

Promise.all([read('./1.txt'), read('./2.txt')]).then(function(data) {    console.log(data);});复制代码

Generator + co

Generator是一个能够返回迭代器的函数,需要在function关键字和名字之间加上*以标识是个Generator,需要配合yield使用,方法每次执行到yield就会暂停,等待返回的迭代器调用next()方法继续往下执行。

next方法

返回一个包含value和done属性的对象,value表示值,done布尔类型,表示迭代是否完成。

co

co库可以自动的将generator进行迭代,同时每次迭代都会返回一个promise

模仿co库的功能

function co(it) {    let task = it();//taskDef生成一个任务迭代器    return new Promise(function(resolve, reject) {        function step(data) {            let {
done, value} = task.next(data); if(!done) { value.then(function(data) { step(data); }, reject); } else { resolve(value); } } step(); }); }复制代码

需求1实现

function *readTask() {    let path = yield read('./1.txt');    let content = yield read(path);    return content;}co(readTask).then(function(data) {    console.log(data); });复制代码

终极方案 asyn await

async和await(语法糖) === co + generator

用async 来修饰函数,aysnc需要配await,await只能promise

需求1实现

async function readTask() {    try {        let path = await read('./1.txt');        let content = await read(path);        return content;    } catch (error) {        throw err;    }}readTask().then(function(data){    console.log(data);});复制代码

转载地址:http://kpmka.baihongyu.com/

你可能感兴趣的文章
React 整洁代码最佳实践
查看>>
聊聊架构设计做些什么来谈如何成为架构师
查看>>
Java并发编程73道面试题及答案
查看>>
移动端架构的几点思考
查看>>
Spark综合使用及用户行为案例区域内热门商品统计分析实战-Spark商业应用实战...
查看>>
初学者自学前端须知
查看>>
Retrofit 源码剖析-深入
查看>>
企业级负载平衡简介(转)
查看>>
ICCV2017 论文浏览记录
查看>>
科技巨头的交通争夺战
查看>>
当中兴安卓手机遇上农行音频通用K宝 -- 卡在“正在通讯”,一直加载中
查看>>
Shell基础之-正则表达式
查看>>
JavaScript异步之Generator、async、await
查看>>
讲讲吸顶效果与react-sticky
查看>>
c++面向对象的一些问题1 0
查看>>
直播视频流技术名词
查看>>
网易跟贴这么火,背后的某个力量不可忽视
查看>>
企业级java springboot b2bc商城系统开源源码二次开发-hystrix参数详解(八)
查看>>
java B2B2C 多租户电子商城系统- 整合企业架构的技术点
查看>>
IOC —— AOP
查看>>