Javascript异步解决方案的发展历程

1.回调函数

function f1(callback){
	setTimeout(function(){
		//f1的任务代码
		callback();
	},1000);
}
f1(f2);
ajax('XXX1', () => {
    // callback 函数体
    ajax('XXX2', () => {
        // callback 函数体
        ajax('XXX3', () => {
            // callback 函数体
        })
    })
})

优点:便于理解
缺点:回调地狱,不能捕获错误

2.事件监听

f1.on('done', f2);
function f1(){
    setTimeout(function () {
      // f1的任务代码
      f1.trigger('done');
    }, 1000);
  }

容易理解,可以绑定多个事件,每个事件可以指定多个回调函数;缺点,整个流程都要变成事件驱动型,运行流程会变得不清晰。

3.发布/订阅(观察者模式)

jQuery.subscribe("done", f2);
function f1(){
    setTimeout(function () {
      // f1的任务代码
      jQuery.publish("done");
    }, 1000);
}
jQuery.unsubscribe("done", f2);

与"事件监听"类似,但是明显优于后者。因为我们可以通过查看"消息中心",了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。

4.Promises对象

Promise就是为了解决callback的问题而产生的
Promise实现了链式调用,也就是说每次then后返回的都是一个全新的Promise,如果我们在 then 中 return ,return 的结果会被 Promise.resolve() 包装

ajax('XXX1')
  .then(res => {
      // 操作逻辑
      return ajax('XXX2')
  }).then(res => {
      // 操作逻辑
      return ajax('XXX3')
  }).then(res => {
      // 操作逻辑
  })

解决了回调地狱的问题,无法取消 Promise ,错误需要通过回调函数来捕获

5.Generator

特点:可以控制函数的执行,Generator函数是协程在ES6中的实现,最大的特点就是可以交出函数的执行权(即暂停执行)
执行Generator函数后会返回一个遍历器对象(Iterator)。本质上Generator是一个状态机,每次的遍历Generator函数返回的都是函数内部的每个状态。

	function* gen() {    
		yield 1;    
		yield 2;    
		return 1;
	  }
	  var g = gen();
	  gen.next() // {value:1,done:false}
	  gen.next() // {value:2,done:false}
	  gen.next() // {value:3,done:true}

Generator函数是分段执行的,yield语句是暂停执行的标记,而next方法可以恢复执行。缺点还需要编写自动执行器

6.使用async函数

async函数的实现就是将Generator函数和自动执行器包装在一个函数中

function async gen(){
	awiat 1;
	awiat 2;
}

异步编程的语法目标,就是怎样让它更像同步编程,使用async/await的方法,使得异步编程与同步编程看起来相差无几了。

7.借助流程控制库

NPM社区中出现了很多流程控制库可以供开发者直接使用,其中很流行的就是async库,该库提供了一些流程控制方法,其官方文档见http://caolan.github.io/async/docs.html
如果需要执行的任务紧密结合。下一个任务需要上一个任务的结果做输入,应该使用瀑布式
如果多个任务必须依次执行,而且之间没有数据交换,应该使用串行执行
如果多个任务之间没有任何依赖,而且执行顺序没有要求,应该使用并行执行

8.使用Web Workers

Web Worker是HTML5新标准中新添加的一个功能,Web Worker的基本原理就是在当前javascript的主线程中,使用Worker类加载一个javascript文件来开辟一个新的线程,起到互不阻塞执行的效果,并且提供主线程和新线程之间数据交换的接口:postMessage,onmessage。其数据交互过程也类似于事件发布/监听模式,异能实现异步操作

9 对比

异步读取文件

1.回调函数

fs.readFile(fileA,(err,data)=>{
	if(err) throw err;
	console.log(data);
	fs.readFile(fileB,(_err,_data)=>{
		if(_err) throw err;
		console.log(_data)
	})
}

2.使用Promise

var fs = require('fs');
var readFile = function(path) {
    return new Promise((resolve, reject) => {
        fs.readFile(path, (err, data) => {
            if (err) reject(err)
            resolve(data)
        })
    })
}
readFile(fileA)
.then((data)=>{console.log(data)})
.then(()=>{return readFile(fileB)})
.then((data)=>{console.log(data)})
// ... 读取n次
.catch((err)=>{console.log(err)})

3.使用Generator

var fs = require('fs');

var readFile = (path) => {
    return new Promise((resolve, reject) => {
        fs.readFile(path, (err, data) => {
            if (err) reject(err)
            resolve(data)
        })
    })
}

var gen = function* () {
    var f1 = yield readFile(fileA);
    var f2 = yield readFile(fileB);
    console.log(f1.toString());
    console.log(f2.toString());
}
gen.next()
grn.next()

4.使用Async

var asyncReadFile = async function() {
    var f1 = await readFile(fileA);
    var f2 = await readFile(fileB);
    console.log(f1.toString())
    console.log(f2.toString())
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值