-
先看Promise关于then的一段代码输出:
Promise.resolve().then(()=>{ console.log(0); return Promise.resolve(4); }).then((res)=>{ console.log(res) }) Promise.resolve().then(()=>{ console.log(1); }).then(()=>{ console.log(2); }).then(()=>{ console.log(3); }).then(()=>{ console.log(5); }).then(()=>{ console.log(6); }) 输出: 0 1 2 3 4 // 发现4被推迟了两个时序,多个promise之间的then是交替运行的 5 6 /* 输出0 -> 首先,浏览器会创建一个 PromiseResolveThenableJob 去处理这个 Promise(resolved) 实例(then后面的函数是返回一个promise的,在函数体里面不可以再返回无状态的promise,否则会陷入无限循环),这是一个微任务。 进入另一个then,输出1 -> 接着,等到下次循环运行到这个微任务时,也就是PromiseResolveThenableJob 执行中的时候,因为这个Promise 实例是fulfilled(resolved)状态,所以又会注册一个它的.then()回调。 进入另一个then,输出2 -> 等到下一次循环到这个Promise 实例,它的.then()回调执行后,才会将参数传给下一个then(输出res,等到下一次循环时,该参数会被输出),于是就被推迟了两个时序 进入另一个then,输出3 -> 接收到参数,输出4 -> 输出5 -> 输出6 */ -
V8引擎关于promise的源码:
当
return Promise.resolve(4)时,相当于return new Promise(resolve=>resolve(4)),这个时候执行return时,会去判断返回的是不是一个promise(IsPromise),是的话,执行x.then,这时候相当于递归调用,递归调用的代码会在下一次事件循环执行(此时已经输出了0,1,接着输出2);之后代码运行到这次递归,执行resolve(4),此时输出3,等到再下一次运行到此处代码时,输出4。 -
resolve的本质:resolve()是用来表示promise的状态为fullfilled,相当于只是定义了一个有状态的Promise,但是并没有调用它;
使用then时需注意:
- promise调用then的前提是该promise的状态为fullfilled
- 只有promise调用then的时候,then里面的函数才会被推入微任务中;
-
单个promise的链式调用:
-
当promise执行时,会创建一个pending状态的promise对象,执行promise函数体中的代码;
-
- 若函数体的状态为fullfilled时,才会调用then的代码,并将then的代码放入此次事件循环的微任务队列中;
- 若函数体的状态为pending时,then后面的代码会被放入该promise中的队列中,等到该promise的状态变为fullfilled时,才将这些代码推入此次事件循环微任务队列中立即执行。
示例:
new Promise((resolve, reject) => { console.log("promise") resolve() }) .then(() => { // 执行.then的时候生成一个promise是给最后一个.then的 console.log("then1") new Promise((resolve, reject) => { console.log("then1promise") resolve() }) .then(() => {// 执行这个.then的时候,生成的promise是下面一个then的 console.log("then1then1") }) .then(() => { console.log("then1then2") }) }) .then(() => { // 这个 console.log("then2") }) 输出: promise then1 then1promise then1then1 then2 then1then2
-