vlambda博客
学习文章列表

总结异步编程的六种方式

众所周知 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')
  8. }

回调函数

因为 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')
  9. }
效果如下:
总结异步编程的六种方式
总结:回调函数易于实现、便于理解,但是多次回调会导致代码高度耦合

事件监听

脚本的执行不取决代码的顺序,而取决于某一个事件是否发生。
事件监听的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. })

参考文献
https://developers.google.com...
http://es6.ruanyifeng.com/ 


总结异步编程的六种方式






如果觉得本文有帮助,欢迎多多转发点赞,推荐给更多的小伙伴哟