问题出处
这个问题是看一篇大佬的文章有点疑惑才去研究的一个问题(额 其实是有点无聊没事干),正好也加深一下Promise的知识。大佬的文章:这一篇浏览器事件循环,可能会颠覆部分人的对宏任务和微任务的理解🤪🤪🤪 - 掘金 (juejin.cn)
在大佬的文章中有一个例子
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);
});
贴一下大佬的说明:(图片)
这里大佬的说明是没有错的,只是我疑惑在了为什么会慢一拍的问题上,接下来是我的验证。
案例1
// 以 函数输出的数字 表示 函数名
Promise.resolve()
.then(() => {
console.log(0);
return 4; // 那我直接返回一个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 4 2 3 5 6 很明显 f4函数 先于 f2函数 先进入微队列,有没有一种正常了的感觉
首先同步执行完成,当前微队列中有 [f0,f1]两个回调函数,先拿出最前面的 f0 出来执行,执行完毕后面调用了then方法,然后往微队列中加入了 f4 函数,当前微队列 [f1,f4] 这两个回调函数,然后在拿出 f1执行,执行完毕-后面调用了then函数,然后往微队列中加入了 f2 函数,当前微队列 [f4,f2] ,然后调用 f4 函数,后面没有了then方法就不添加队列,当前微队列 [f2],取出 f2 执行后面的顺序执行
那又为什么就改变了返回值就造成了这样的问题呢?那返回其他的呢?
案例二
// 以 函数输出的数字 表示 函数名
Promise.resolve()
.then(() => {
console.log(0);
return 4;
// 那我直接返回一个4会怎么样呢?
// 输出:0 1 4 2 3 5 6
// return '4' 字符串
// 输出:0 1 4 2 3 5 6
// return [4] 数组
// 输出:0 1 [4] 2 3 5 6
// return {} 对象
// 输出:0 1 {} 2 3 5 6
// return undefined | null
// 输出:0 1 undefined | null 2 3 5 6
// return true | false Boolean
// 输出:0 1 Boolean 2 3 5 6
// return Symbol(4) Symbol
// 输出:0 1 Symbol(4) 2 3 5 6
// return ()=> 4 返回普通函数也是一样后入队列
// 输出:0 1 () => 4 2 3 5 6
// return 没有返回值
// 输出:0 1 undefined 4 2 3 5 6
// 不写 return
// 输出:0 1 undefined 4 2 3 5 6
// 以上都是一样的输出
// return { 返回一个这样
// then: () => 4,
// };
// 输出:1 2 3 5 6
// return { 一个对象中带有then方法
// then(resolve) {
// resolve(4);
// },
// };
// 输出:0 1 2 4 3 5 6 =====> 不一样了!!!
// return new Promise((resolve) => {
// resolve(4);
// });
// 输出:0 1 2 3 4 5 6 =====> 与大佬的例子输出一致
})
.then((res) => {
console.log(res);
});
xxxxxx代码
总结:
根据以上代码明确了一个事情,当你返回了一个不是对象类型或是一个对象没有then方法都会按照一般理解来调用,当返回是一个对象会检测then方法,会自动的调用then方法看有没有使用 resolve() 来返回东西。
也就是Promise的链式调用是根据你的返回值来判断是否把 回调函数 放入队列中,Promise.then方法会自动返回一个Promise对象,当我们伪造了一个对象(带有then方法)浏览器会把这个 回调函数 往后放一位就是慢了一拍,而返回的是一个Promise对象(不论这个Promise是什么状态的)都会往后放两位。
所以 Promise的链式调用是根据你的返回值来判断情况
在总结:
这个在实际中估计十年碰不到一次 ,水文一篇。