https://blog.csdn.net/daydream13580130043/article/details/83105098
javascript是单线程的语言,所以在执行任务的时候,所有任务必须排队,然后一个一个的执行,在js中分同步代码和异步代码。js有个任务队列,用来存放异步代码。任务队列中的任务又有优先级之分,微任务microtask的优先级大于宏任务macrotask,在js中代码的执行顺序为:主线程会先执行完同步代码,并将异步代码放到任务队列中,当同步代码执行完毕后,就轮询任务队列,先询问微任务,如果有则执行微任务,如果没有询问宏任务。
js任务的执行顺序JS中异步实现方式的种类:
1. callback回调函数
2. ES6的Promise对象
3. ES7的async/await
callback回调函数
回调函数的定义:A callback is a function that is passed as an argument to another function and is executed after its parent function has completed。回调函数就是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。这个过程就叫做回调。回调,就是回头调用的意思。主函数的事先干完,回头再调用传进来的那个函数。
js callback function回调的好处就是容易编写,缺点就是过多的回调会产生回调地狱,代码横向扩展,代码可读性变差。
callback多层嵌套ES6的promise对象
Promise是一个对象,用于处理异步操作,让我们写异步调用的时候更加优雅和便于阅读。promise为承诺,意思是使用了Promise之后它肯定会给我们一个答复,无论成功还是失败都会给出结果。
Promise有3种状态:
pending(进行中,未完成的)
resolved(已完成,又称fullfilled)
rejected(已失败)
promise的过程一般只有2种:
pending -> resolved
pending -> rejected
1. promise从未完成的状态开始,如果成功promise是完成状态;如果失败会是失败状态。
2. 当一个promise转变为完成状态,所有注册到它的成功回调函数将被调用,而且会把结果传递给成功回调函数。
3. 当一个promise转变为失败状态,所有注册到它的失败回调函数将被调用,而且会把结果传递给失败回调函数。
4. 对包含前进特性的promise实例来说,promise 在它离开未完成状态以前的任何时刻,都可以更新它的 progress。当 progress 被更新,所有的前进回调(progress callbacks)会被传递以 progress 的值,并被立即调用。前进回调被以不同于成功和失败回调的方式处理;如果你在一个 progress 更新已经发生以后注册了一个前进回调,新的前进回调只会在它被注册以后被已更新的 progress 调用。???
5. 只有异步操作的结果,可以决定当前promise实例的状态,其他操作都无法改变其状态。
promise状态图promise对象的then方法,用来执行回调函数。then方法接受2个参数:1. resolved之后的成功回调函数;2. rejected之后的失败回调函数(可选)3. 前进回调函数?。then方法也可以返回promise对象,这样就可以链式调用了。
promise then链式调用then()方法
then()方法就是把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。可以在then方法中继续创建promise对象并返回,这样可以再调用then执行下一个回调函数。
函数定义 使用then链式调用上面的then链式调用也可以简写为:
简写版reject()方法
通过调用resolve方法把promise设置为完成状态(resolved),这时then方法就能捕捉到变化,并执行成功回调函数(then方法的第一个参数)。而reject方法就是把promise设置为失败状态(rejected),这时then方法执行失败回调函数(then方法的第二个参数)。
多重嵌套callback可能会造成无法捕获异常,如果使用promise,可以通过reject方法把promise的状态设置为rejected,然后在失败回调函数中处理异常:
在失败回调函数中处理异常catch()方法
也可以在catch方法中处理异常:
catch语句处理异常使用catch方法,当实行成功回调函数时,如果出现了异常,程序也不会中断,而是进入到catch方法中:
捕获成功回调函数异常错误捕获是非常有用的,可以帮助我们在开发中识别代码错误。例如,在一个then()方法内部的出现TyprError的异常,如果用失败回调函数处理,错误就会被吞没掉,但是用catch方法处理,就可以更加精准地捕获异常:
精准地捕获异常all()方法
Promise的all()方法提供了并行执行异步操作的功能,并且在所有异步操作执行完成后才执行回调函数:
all()方法race()方法
race()方法和all()方法一样提供了并行执行异步操作的功能,但是只要有一个异步操作执行完成,就会立即执行回调函数,其他没有完成的异步函数会继续执行,不会被中断。
race()方法利用race()方法给某个异步操作设置一个timeout值,一旦超过设置的执行事件,调用异常处理函数catch,但是这个异步操作还会继续执行:
timerasync/await是ES7的重要特性之一,是新的解决异步问题的方案。async/await是建立在promise基础之上的,是非阻塞的。async函数返回的是一个promise对象,如果在async函数中直接返回一个直接量,async会把这个直接量通过Promise.resolve()封装成Promise对象。如果async没有返回值,Promise的“resolve”statue就是undefined。
async函数返回Promise对象async函数返回Promise函数,所以可以使用then方法添加回调函数。当async函数执行的时候,遇到await关键字时,就会先等到await修饰的异步操作完成之后,再继续执行async函数中await下面的代码,但是async函数并没有阻塞其后面的代码,所以先打印了d:
async/awaitasync/await实现原理
async相当于Generator+自动执行器,是generator的语法糖。先简单学习一个js的generator:
1. 如果某个函数中有yield,说明这个函数是一个生成器generator。
2. yield需要配合next()函数配合使用,每次调用返回2个值:{value:"迭代结果", done: false/true(是否迭代完成)}
3. yield并不直接产生值,而是产生一个待输出的函数
4.next()可以无限调用,但迭代器中的步骤迭代完成之后,总是返回undfined
5. 如果yield是表达式的一部分,需要用()单独括起来
yieldyield可以使函数体分段执行,而不是一旦调用函数,就把函数从头到尾的执行一遍,需要用next()来控制代码的进度。所以可以用yield来处理异步函数,当异步函数执行完成后,再使用next()执行函数接下来的代码。
网友评论