Javascript语言的执行环境是单线程的。也就是说,一次只能完成一项任务。如果有多个任务,则需要排队一个一个执行——上一个任务完成,再执行下一个任务。这种执行方式实现简单,执行环境也比较简单。但是随着前端业务越来越复杂,事务和请求的数量越来越多,这种单线程的执行方式在复杂的业务情况下势必效率低下。只要一个任务耗时长,后面的任务就必须排队等待,这样就会拖延整个程序的执行。常见的浏览器无响应(假死),往往是因为某段Javascript代码运行时间过长(比如死循环),导致整个页面卡在这个地方,无法执行其他任务。为了避免和解决这个问题,JS语言将任务执行方式分为异步和同步两种。“同步模式”就是上一段中的模式,后一个任务等待前一个任务结束,然后执行,程序的执行顺序与任务的排列顺序一致,同步;“异步模式”则完全不同,每个任务都有一个或多个回调函数(callback),前一个任务结束后,执行回调函数而不是下一个任务,后一个任务执行时无需等待前一个任务完成end,所以程序的执行顺序和task的执行顺序是不一致的,是异步的。“异步模式”非常重要。在浏览器端,长时间的操作应该异步执行,避免浏览器丢失响应。最好的例子是Ajax操作。在服务器端,“异步模式”甚至是唯一的模式,因为执行环境是单线程的。如果让所有http请求同步执行,服务器性能会急剧下降,很快就会失去响应。1回调函数异步编程的最基本方法。首先,你需要Statement,回调函数只是一个实现,并不是异步模式的唯一实现。回调函数也可以用在同步(阻塞)场景等场景。回调函数的英文定义:回调是作为参数传递给另一个函数并在其父函数完成后执行的函数。从字面上理解,回调函数就是一个参数,这个函数作为参数传递给另一个函数。那个函数执行完之后,再执行传入的这个函数。这个过程称为回调。在JavaScript中,回调函数的具体定义是:函数A作为参数(函数引用)传递给另一个函数B,这个函数B执行函数A。我们说函数A叫做Callback。如果没有名称(函数表达式),则称为匿名回调函数。2promise随着ES6标准的发布,处理异步数据流的方案发生了新的变化。承诺就是其中之一。我们都知道,在传统的ajax请求中,当异步请求之间的数据之间存在依赖关系时,可能会产生难看的多层回调,容易造成代码逻辑混乱,后期难以阅读和维护。俗称“回调地狱”。另一方面,错误处理代码往往与正常的业务代码耦合在一起,使得代码极其丑陋。为了让编程更好,我们需要引入promises来降低异步编程的复杂度。Promise是一种异步解决方案。它有三种状态:pending(等待)、fulfilled(完成)和rejected(失败)。简单实现://极简实现+链式调用+延迟机制+stateclassPromise{callbacks=[];state='pending';//添加状态value=null;//保存结果constructor(fn){fn(this._resolve.bind(this));}then(onFulfilled){if(this.state==='pending'){//在resolve之前,加入回调this.callbacks.push,逻辑同之前(onFulfilled);}else{//resolve后直接执行回调并返回结果onFulfilled(this.value);}返回这个;}_resolve(value){this.state='fulfilled';//改变this的状态.value=value;//保存结果this.callbacks.forEach(fn=>fn(value));}}3Generator函数Generator函数是ES6中coroutine的实现,最大的特点是可以交出函数的执行权(即挂起执行)。整个Generator函数就是一个封装好的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方用yield语句标示。Generator函数可以挂起和恢复执行,这是它可以封装异步任务的根本原因。此外,它还有两个特性使其成为异步编程的完整解决方案:函数体内外的数据交换和错误处理机制4async和awaitasync函数是目前函数回调的最佳解决方案。async函数返回一个Promise对象。函数在执行时,一旦遇到await,会先返回,等待触发的异步操作完成,然后在函数体中执行下面的语句。要理解async函数,首先要理解Generator函数,因为async函数是Generator函数的语法糖。async的简单实现//定义一个promise模拟一个异步请求,作用是传入参数++functiongetNum(num){returnnewPromise((resolve,reject)=>{setTimeout(()=>{resolve(num+1)},1000)})}//自动执行器,如果一个Generator函数没有执行,则递归调用函数asyncFun(func){vargen=func();functionnext(data){varresult=gen.next(data);如果(结果。完成)返回结果。值;结果.value.then(函数(数据){next(数据);});}next();}//生成器要执行的函数,执行完一步的promise后执行内部数据,然后调用下一步varfunc=function*(){varf1=yieldgetNum(1);varf2=yieldgetNum(f1);控制台日志(f2);};asyncFun(函数);
