异步编程众所周知JavaScript是单线程工作的,即一个脚本执行完才能执行下一个脚本,不能同时执行两个脚本时间。如果一个脚本耗时较长,后面的所有脚本都要排队等候,这样会延迟整个程序的执行。那么如何让程序像人一样多线程工作呢?下面总结了几种异步编程的方法,希望对大家有所启发。回调函数事件监听器发布订阅模式PromiseGenerator(ES6)async(ES7)异步编程的传统解决方案:回调函数和事件监听器初始示例:假设有两个函数,f1和f2,f1是一个函数,它接受某个多少时间。functionf1(){setTimeout(function(){console.log('先执行f1')},1000)}functionf2(){console.log('executef2')}回调函数,因为f1是一个耗时函数,所以f2可以写成f1的回调函数,把同步操作变成异步操作,f1不会阻塞程序的运行,f2也不需要什么都不等待,比如JQuery的ajax。回调函数的demo:functionf1(f2){setTimeout(function(){console.log('executef1first')},1000)f2()}functionf2(){console.log('executef2')}效果如下:小结:回调函数实现简单,容易理解,但是多次回调会导致代码耦合度高。事件监控脚本的执行不依赖于代码的顺序,而是依赖于某个事件是否发生。demo$(document).ready(function(){console.log('DOM准备就绪')});事件监听的发布-订阅模式。发布/订阅模式使用消息中心,发布者向消息中心发布消息。订阅者从消息中心订阅消息。类似于vue的父子组件之间的传值。发布订阅模式演示//订阅done事件$('#app').on('done',function(data){console.log(data)})//发布事件$('#app').trigger('done,'哈哈')PromisePromise其实是一个对象,从中可以得到异步操作的消息,Promise对象有三种状态,pending(进行中),fulfilled(成功)和rejected(失败)。Promise的状态一旦改变,就不会再改变,将回调函数变为链式调用。Promise封装异步请求demoexportdefaultfunctiongetMethods(url){returnnewPromise(function(resolve,reject){axios.get(url).then(res=>{resolve(res)}).catch(err=>{reject(err)})})}getMethods('/api/xxx').then(res=>{console.log(res)},err=>{console.log(err)})GeneratorGenerator函数是一个状态机,封装了多个内部状态.执行Generator函数会返回一个遍历器对象,使用该对象的next()方法,可以遍历Generator函数内部的各个状态,直到return语句。形式上,Generator函数是一个普通函数,但具有两个特征。首先,函数关键字和函数名之间有一个星号;其次,函数体内使用了yield表达式,yield是暂停执行的标志。当next()方法遇到yield表达式时,会暂停后续操作的执行,将紧跟在yield后面的表达式的值作为返回对象的value属性。Generator的demofunction*generatorDemo(){yield'hello';yield1+2;return'ok';}vardemo=generatorDemo()demo.next()//{value:'hello',done:false}demo.next()//{value:3,done:false}demo.next()//{value:'ok',done:ture}demo.next()//{value:undefined,done:ture}由异步函数返回它是一个Promise对象,可以使用then方法添加回调函数,async函数内部return语句返回的值会成为then方法回调函数的参数。函数在执行时,一旦遇到await,会先返回,等待异步操作完成,然后在函数体中执行下面的语句。1、await命令后返回Promise对象,运行结果可能会被拒绝,所以最好将await命令放在try...catch代码块中。async的demo1asyncfunctiondemo(){try{awaitnewPromise(function(resolve,reject){//something});}catch(err){console.log(err);}}demo().then(data=>{console.log(数据)//})
