总结异步编程的六种方式

开发 前端
众所周知 JavaScript 是单线程工作,也就是只有一个脚本执行完成后才能执行下一个脚本,那么如何让程序像人类一样可以多线程工作呢?以下为几种异步编程方式的总结,希望与君共勉。

 [[265412]]

异步编程

众所周知 JavaScript 是单线程工作,也就是只有一个脚本执行完成后才能执行下一个脚本,两个脚本不能同时执行,如果某个脚本耗时很长,后面的脚本都必须排队等着,会拖延整个程序的执行。那么如何让程序像人类一样可以多线程工作呢?以下为几种异步编程方式的总结,希望与君共勉。

  •  回调函数
  •  事件监听
  •  发布订阅模式
  •  Promise
  •  Generator (ES6)
  •  async (ES7)

异步编程传统的解决方案:回调函数和事件监听

初始示例:假设有两个函数, f1 和 f2,f1 是一个需要一定时间的函数。 

  1. function f1() {  
  2.     setTimeout(function(){  
  3.         console.log('先执行 f1')  
  4.     },1000)  
  5.  
  6. function f2() {  
  7.     console.log('再执行 f2')  

回调函数

因为 f1 是一个需要一定时间的函数,所以可以将 f2 写成 f1 的回调函数,将同步操作变成异步操作,f1 不会阻塞程序的运行,f2 也无需空空等待,例如 JQuery 的 ajax。

回调函数的demo: 

  1. function f1(f2){  
  2.     setTimeout(function(){  
  3.         console.log('先执行 f1')  
  4.     },1000)  
  5.     f2()  
  6.  
  7. function f2() {  
  8.     console.log('再执行 f2')  

效果如下:

总结:回调函数易于实现、便于理解,但是多次回调会导致代码高度耦合

事件监听

脚本的执行不取决代码的顺序,而取决于某一个事件是否发生。

事件监听的demo 

  1. $(document).ready(function(){  
  2.      console.log('DOM 已经 ready')  
  3. }); 

发布订阅模式

发布/订阅模式是利用一个消息中心,发布者发布一个消息给消息中心,订阅者从消息中心订阅该消息,。类似于 vue 的父子组件之间的传值。

发布订阅模式的 demo 

  1. //订阅done事件  
  2. $('#app').on('done',function(data){  
  3.     console.log(data)  
  4. })  
  5. //发布事件  
  6. $('#app').trigger('done,'haha') 

Promise

Promise 实际就是一个对象, 从它可以获得异步操作的消息,Promise 对象有三种状态,pending(进行中)、fulfilled(已成功)和rejected(已失败)。Promise 的状态一旦改变之后,就不会在发生任何变化,将回调函数变成了链式调用。

Promise 封装异步请求demo 

  1. export default function getMethods (url){  
  2.     return new Promise(function(resolve, reject){  
  3.         axios.get(url).then(res => {  
  4.             resolve(res)  
  5.         }).catch(err => 
  6.             reject(err)  
  7.         })  
  8.     })  
  9.  
  10. getMethods('/api/xxx').then(res => {  
  11.     console.log(res)  
  12. }, err => {  
  13.     console.log(err)  
  14. }) 

Generator

Generator 函数是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象,使用该对象的 next() 方法,可以遍历 Generator 函数内部的每一个状态,直到 return 语句。

形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式, yield是暂停执行的标记。

next() 方法遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。

Generator 的 demo 

  1. function *generatorDemo() {  
  2.   yield 'hello';  
  3.   yield  1 + 2;  
  4.   return 'ok';  
  5.  
  6. var demo = generatorDemo()  
  7. demo.next()   // { value: 'hello', done: false }   
  8. demo.next()   // { value: 3, done: false }   
  9. demo.next()   // { value: 'ok', done: ture }   
  10. demo.next()   // { value: undefined, done: ture }  

async

async函数返回的是一个 Promise 对象,可以使用 then 方法添加回调函数,async 函数内部 return 语句返回的值,会成为 then 方法回调函数的参数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

1.await命令后面返回的是 Promise 对象,运行结果可能是rejected,所以***把await命令放在try...catch代码块中。

async 的 demo1 

  1. async function demo() {  
  2.   try {  
  3.     await new Promise(function (resolve, reject) {  
  4.       // something  
  5.     });  
  6.   } catch (err) { 
  7.     console.log(err);  
  8.   }  
  9.  
  10. demo().then(data => {  
  11.     console.log(data)  //   
  12. }) 
责任编辑:庞桂玉 来源: segmentfault
相关推荐

2019-01-17 10:58:52

JS异步编程前端

2017-06-26 10:35:58

前端JavaScript继承方式

2009-02-11 09:46:00

ASON网络演进

2022-05-12 09:02:50

编程语言PythonJava

2022-03-23 12:55:50

农业物联网

2017-10-20 11:07:45

编程代码编程模式

2020-07-31 11:12:39

安全威胁网络攻击网络安全

2020-04-27 09:00:00

双因素认证身份认证生物识别

2022-01-14 10:34:50

黑客隐藏踪迹网络安全

2023-05-10 13:58:13

服务限流系统

2021-01-08 10:52:22

物联网万物互联IoT,Interne

2018-08-03 16:40:06

前端前端框架微服务

2010-09-13 18:02:46

2022-07-15 10:30:41

ITCIO

2023-10-30 11:53:37

继承JS父类

2018-10-19 10:30:51

SD-WAN软件定义广域网网络

2023-08-11 13:39:06

首席信息官IT领导

2022-03-28 20:57:31

私有属性class属性和方法

2023-12-06 18:21:12

编程语言AI开发AI

2024-10-15 08:29:09

C#软件开发
点赞
收藏

51CTO技术栈公众号