动力节点首页 全国咨询热线:400-8080-105

绑定手机号,登录
手机号

验证码

微信登录
手机号登录
手机号

验证码

微信登录与注册
微信扫码登录与注册

扫码关注微信公众号完成登录与注册
手机号登录
首页 > 文章

JavaScript异步编程详解

04-28 17:24 674浏览
举报 T字号
  • 大字
  • 中字
  • 小字

我们都知道,JavaScript是单线程的,也就是说,同步代码很有可能会阻塞任务。如果我们使用异步编程,就可以避免阻塞后面的代码的执行。现在主流的异步编程方案主要分为四种,接下来我们一个一个的来看。

1.回调函数

用最简单的回调函数来做例子:

 function f1(callback) {
       setTimeout(function() { // f1的任务代码
             callback();
       }, 1000);
 }
 f1(f2)

通过setTimeout callback函数把同步操作变成了异步。

回调函数的优点便是:简单、容易理解、优化了程序执行速度;

缺点也很明显:不便于代码阅读和理解、各个部分高度耦合,而且每个任务只能指定一个回调函数。

更不方便的是,如果某个业务,依赖于上层业务的数据,上层业务又依赖于更上一层的数据,我们还采用回调的方式来处理异步的话,就会出现回调地狱。

2.Promise

Promise在一定程度上解决了回调地狱的问题,Promise在一定程度上其实改善了回调函数的书写方式,无论有再多的业务依赖,通过多个then(...)来获取数据,让代码只在纵向进行扩展;

另外一点就是逻辑性更明显了,将异步业务提取成单个函数,整个流程可以看到是一步步向下执行的,依赖层级也很清晰,最后需要的数据是在整个代码的最后一步获得。(当然前提是实现的Promise完全遵循PromiseA+规范)

        const p1 = Promise.resolve(1) 
        const p2 = Promise.resolve(Promise.resolve(3))
        const p3 = Promise.resolve(Promise.reject(4))
        p1.then(value => {
            console.log('p1', value)
        })
        p2.then(value => {
            console.log('p2', value)
        })
        p3.catch(reason => {
            console.log('p3', reason)
        })

3.Generator

生成器Generator是ES6中定义的,它是一种顺序、看似同步的异步流程控制表达风格。

在这之前我们先看看两个ES6新增的协议:可迭代协议和迭代器协议

A:可迭代协议(for of循环)

允许对象定义他的可迭代行为,比如在for of结构中,哪些值可以遍历到。在js中的某些类型是内置好的可迭代对象,比如:字符串、数组、类型数组、Map对象、Get对象等。而Object类型不可迭代。这些内置可迭代对象可以进行迭代的原因是内部实现了@@iterator 方法,即在该对象或该对象的原型链上有Symbol.iterator属性实现了@@iterator 方法。

B:迭代器协议:(Iterator对象)

定义了产生一系列值的标准方式。一个对象必须实现next()方法,才能成为迭代器。 next() 方法必须返回一个对象,该对象应当有两个属性: done 和 value done(boolean)如果迭代器可以产生序列中的下一个值,则为 false。 value 迭代器返回的任何 JavaScript 值

C:用Generator实现异步

const fs = require('fs');
const co = require('co');
const bluebird = require('bluebird');
const readFile = bluebird.promisify(fs.readFile);

function* read() {
    yield readFile(A, 'utf-8');
    yield readFile(B, 'utf-8');
    yield readFile(C, 'utf-8');
    //....
}
co(read()).then(data => {
    //code
}).catch(err => {
    //code
});

也就是说,Generator生成器解决了Promise没有解决的纵向扩展。

4.Async/Await

Async/Await是ES7新引入的概念。他就是结合了上面所说的Promise和Generator,用同步的方式实现异步操作。

我们简单看一段使用async/await的代码:

        async function fn3() {
            try {
                const value = await fn2() // await右侧表达式为promise,得到结果promise成功的value
                console.log('value', value);
            } catch (error) {
                console.log('失败的结果', error)
            }
        }
        fn3()

可以看出,用的同步的书写方式,只需要把异步的东西用Promise封装出去,然后使用await调用就可以了,也不需要像Generator一样需要手动控制next()执行。

目前来说,Async/Await是最好的异步编程方案了,几乎能够完美地达到JavaScript的伪多线程

0人推荐
共同学习,写下你的评论
0条评论
代码小兵279
程序员代码小兵279

75篇文章贡献270037字

相关课程 更多>

作者相关文章更多>

推荐相关文章更多>

Java面试题及答案整理

提枪策马乘胜追击04-21 20:01

Spring常见面试题

代码小兵92504-17 16:07

Java零基础实战项目——五子棋

代码小兵98804-25 13:57

Java string类详解

杨晶珍05-11 14:54

6道经典算法面试题

杨晶珍05-12 16:39

发评论

举报

0/150

取消