promise和async

由于javascript是单线程的,只能在JS引擎的主线程上运行的,所以js代码只能一行一行的执行,不能在同一时间执行多个js代码任务,这就导致如果有一段耗时较长的计算,或者是一个ajax请求等IO操作,如果没有异步的存在,就会出现用户长时间等待,并且由于当前任务还未完成,所以这时候所有的其他操作都会无响应。

那么常见的异步模式有哪些呢?

回调函数

事件监听

发布/订阅模式(又称观察者模式)

promise

具体JS是如何实现异步操作的呢?

当JS解析执行时,会被引擎分为两类任务,同步任务(synchronous) 和 异步任务(asynchronous)。

对于同步任务来说,会被推到执行栈按顺序去执行这些任务。对于异步任务来说,当其可以被执行时,会被放到一个 任务队列(task queue) 里等待JS引擎去执行。

当执行栈中的所有同步任务完成后,JS引擎才会去任务队列里查看是否有任务存在,并将任务放到执行栈中去执行,执行完了又会去任务队列里查看是否有已经可以执行的任务。这种循环检查的机制,就叫做事件循环(Event Loop)。

1.回调函数:当一个函数作为参数传入另一个参数中,并且它不会立即执行,只有当满足一定条件后该函数才可以执行,这种函数就称为回调函数。我们熟悉的定时器和Ajax中就存在有回调函数:

2.回调地狱:存在异步执行的代码,不能按顺序执行,所以代码回调函数嵌套回调函数,形成回调地狱

3.promise

主要用于异步计算:作用:为了避免界面冻结

Promise是js中的一个原生对象,是一种异步编程的解决方案,可以替换掉传统的回调函数解决方案。

promise构造函数接收一个函数作为参数,需要异步任务就卸载该函数体,该函数的两个参数是resolve,reject,异步任务执行成功时调用resolve,错误调用reject

promise对象的then方法用来接收处理成功时响应的数据,catch方法用来接收处理失败的函数

promise的链式编程可以保证代码的执行顺序,前提是每一次在then做完处理后一定要return一个promise对象,这样才能在下一次then时接收到数据

假如在.then()的函数里面不返回新的promise,会怎样?

.then()

1、接收两个函数作为参数,分别代表fulfilled(成功)和rejected(失败) 2、.then()返回一个新的Promise实例,所以它可以链式调用 3、当前面的Promise状态改变时,.then()根据其最终状态,选择特定的状态响应函数执行 4、状态响应函数可以返回新的promise,或其他值,不返回值也可以我们可以认为它返回了一个null; 5、如果返回新的promise,那么下一级.then()会在新的promise状态改变之后执行 6、如果返回其他任何值,则会立即执行下一级.then()

promise有三个状态:1、pending[待定]初始状态2、fulfilled[实现]操作成功3、rejected[被否决]操作失败

Promise会自动捕获内部异常,并交给rejected响应函数处理。

错误处理两种做法: 第一种:reject('错误信息').then(() => {}, () => {错误处理逻辑}) 第二种:throw new Error('错误信息').catch( () => {错误处理逻辑}) 推荐使用第二种方式,更加清晰好读,并且可以捕获前面所有的错误(可以捕获N个then回调错误)

async和await

异步函数是使用async关键字声明的函数,其中允许使用await关键字。async和await关键字使基于承诺的异步行为能够以更简洁的风格编写,从而避免了显式配置承诺链的需要。

async

作为一个关键字放在函数的前面,表示该函数是一个异步函数,意味着该函数的执行不会阻塞后面代码的执行 异步函数的调用跟普通函数一样

await

await即等待,用于等待一个promise对象。只能在异步函数async function使用,他的返回值不是promise对象而是promise对象处理的结果,await表达式会暂停当前async function的执行,等待promise处理完成。若promise正常处理(fulfilled),其回调的resolve函数参数作为await的表达式的值,继续执行async function,若promise处理异常(rejected),await表达式会把promise的异常原因抛出,如果 await 操作符后的表达式的值不是一个 Promise,那么该值将被转换为一个已正常处理的 Promise

与Promise对比1、不再需要多层.then方法假设一个业务分很多步骤完成,并且每个步骤都是异步,依赖上一个步骤的结果。

2、可以对Promise进行并行处理

function takeLongTime(n) {
   return new Promise(resolve => {
       setTimeout(() => resolve(n + 200), n);
   });
}
function step1(n) {
   console.log(`step1 with ${n}`);
   return takeLongTime(n);
}
function step2(n) {
   console.log(`step2 with ${n}`);
   return takeLongTime(n);
}
function step3(n) {
   console.log(`step3 with ${n}`);
   return takeLongTime(n);
}

Promise方式

function doIt() {
   console.time("doIt");
   const time1 = 300;
   step1(time1)
       .then(time2 => step2(time2))
       .then(time3 => step3(time3))
       .then(result => {
           console.log(`result is ${result}`);
           console.timeEnd("doIt");
       });
}
doIt();

// async await方式

async function doIt() {
   console.time("doIt");
   const time1 = 300;
   const time2 = await step1(time1);
   const time3 = await step2(time2);
   const result = await step3(time3);
   console.log(`result is ${result}`);
   console.timeEnd("doIt");
}
doIt();
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容