美文网首页
JS异步发展历程

JS异步发展历程

作者: 易推倒DE小狼 | 来源:发表于2019-07-13 14:29 被阅读0次

最近在看nodejs相关的内容,正好有提到几个异步调用的例子,于是想借着这个机会整理一下JS的异步发展历程,做下整理。

先来了解下什么是异步?

当前一个任务被执行时,不会等待任务执行完成后就去执行下一个任务,等前一个任务执行完成后,将去执行其返回的回调函数,这就是异步操作。

那JavaScript 中为什么需要异步?

首先我们知道JavaScript是单线程的(即使新增了webworker,但是本质上JS还是单线程)。同步代码意味着什么呢?意味着有可能会阻塞,当我们有一个任务需要时间较长时,如果使用同步方式,那么就会阻塞之后的代码执行。而异步则不会,我们不会等待异步代码的之后,继续执行异步任务之后的代码。

解决方案:

1. 回调函数callback

被作为实参传入另一函数,并在该外部函数内被调用,用以来完成某些任务的函数。如setTimeOut,ajax请求,readFile等。

function greeting(name){
  console.log("Hello,"+name);
}
function processUserInput(callback){
  let name = prompt("请输入你的名字");
  callback(name);
}
processUserInput(greeting);

优点:
解决了异步的问题。
缺点:
回调地狱:多个回调函数嵌套的情况,使代码看起来很混乱,不易于维护。

2. Promise

Promise是es6提出的异步编程的一种解决方案。
Promise 对象有三种状态:

  • pending: 初始状态,既不是成功,也不是失败状态。
  • fulfilled: 意味着操作成功完成。
  • rejected: 意味着操作失败。
    promise的状态只能从pending变成fulfilled,和pending变成rejected,状态一旦改变,就不会再改变,且只有异步操作的结果才能改变promise的状态。
    例:
function read(url){
  return new Promise((resolve,reject) => {
    fs.readFile(url,'utf-8',(err, data) => {
      if(err) reject(err);
      resolve(data);
    })
  })
}
read(A).then(data => {
  return read(B);
}).catch(reason => {
  console.log(reason);
})

优点:解决了回调地狱的问题,将异步操作以同步操作的流程表达出来。
缺点:无法取消promise。如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。当执行多个Promise时,一堆then看起来也很不友好。

3. Generator

Generator是es6提出的另一种异步编程解决方案,需要在函数名之前加一个*号,函数内部使用yield语句。Generaotr函数会返回一个遍历器,可以进行遍历操作执行每个中断点yield。

function *count(){
  yield 1;
  yield 2;
  return 3;
}
let c = count();
console.log(c.next());  // { value: 1, done: false }
console.log(c.next()); // { value: 2, done: false }
console.log(c.next()); // { value: 3, done: true }
console.log(c.next()); // { value: undefined, done: true }

优点:没有了Promise的一堆then(),异步操作更像同步操作,代码更加清晰。
缺点:不能自动执行异步操作,需要写多个next()方法,需要配合使用Thunk函数和Co模块才能做到自动执行。

4. async/await

async是es2017引入的异步操作解决方案,可以理解为Generator的语法糖,async等同于Generator和co模块的封装,async 函数返回一个 Promise。

async function read() {
 let readA = await readFile('data/a.txt')
 let readB = await readFile('data/b.txt')
 let readC = await readFile('data/c.txt')

 console.log(readA)
 console.log(readB)
 console.log(readC)
}
read()

优点:内置执行器,比Generator操作更简单。async/await比*/yield语义更清晰。返回值是Promise对象,可以用then指定下一步操作。代码更整洁。可以捕获同步和异步的错误。
缺点:暂时没有人提及这种写法的缺点,目前前端圈一致推荐的异步操作的写法。

总结:

JS的异步发展史,可以认为是从 callback -> promise -> generator -> async/await。async/await 使得异步代码看起来像同步代码,异步编程发展的目标就是让异步逻辑的代码看起来像同步一样。

参考:

  1. 滴滴:JS异步解决方案的发展历程及优缺点
  2. 细说JS异步发展流程

相关文章

  • JS异步发展历程

    最近在看nodejs相关的内容,正好有提到几个异步调用的例子,于是想借着这个机会整理一下JS的异步发展历程,做下整...

  • 细说JS异步发展历程

    知其然知其所以然,首先了解三个概念: 1.什么是同步? 所谓同步,就是在发出一个"调用"时,在没有得到结果之前,该...

  • web前端面试3

    1 JS异步解决方案的发展历程以及优缺点 1,回调函数(无法捕获错误(使用try catch) 不能return)...

  • 异步

    JS 异步解决方案的发展历程以及优缺点。 1、回调函数(callback)优点:解决了同步的问题(只要有一个任务耗...

  • js异步发展简史

    什么是异步? 所谓异步,简单来说就是异步任务(不会马上就完成的任务);但是js不会等待你这个任务完成,而是直接执行...

  • 异步发展历程,js走过的那十年

    js中异步的发展跌跌撞撞走了十年,从开始的回调恶魔发展到现在的仿佛同步的写法。再次回顾,特此总结。 先简述一下我们...

  • vue3.0有哪些变化?

    ** 发展历程** vue.js1.x-----vue.js2.x 引入了虚拟DOM vue.js2.x问题 1)...

  • 你不知道的JS(中卷)第七章

    第七章 回调 回调是js异步的基本单元。随着js越来越成熟,对于异步编程的发展,回调已经不够用了。回调表达异步流的...

  • JS异步那些事 一 (基础知识)

    JS异步那些事 一 (基础知识)JS异步那些事 二 (分布式事件)JS异步那些事 三 (Promise)JS异步那...

  • JS异步那些事 三 (Promise)

    JS异步那些事 一 (基础知识)JS异步那些事 二 (分布式事件)JS异步那些事 三 (Promise)JS异步那...

网友评论

      本文标题:JS异步发展历程

      本文链接:https://www.haomeiwen.com/subject/chmpkctx.html