promise的执行顺序(由一道bilibili面试题看Promise异步执行机制)

本文目录
由一道bilibili面试题看Promise异步执行机制
求上面的输出顺序和输出值,为什么?
答案:
其中,关于时间差结果可能因为计算机性能造成的微小差异,可忽略不计
你答对了吗?下面我们由浅入深探索本题
首先,看一下 event loop 的基础必备内容
event loop 执行顺序:
微任务包括: MutationObserver 、 Promise.then()或catch() 、 Promise为基础开发的其它技术,比如fetch API 、 V8 的垃圾回收过程、 Node独有的process.nextTick 、 Object.observe (已废弃; Proxy 对象替代)
宏任务包括 : script 、 setTimeout 、 setInterval 、 setImmediate 、 I/O 、 UI rendering 、 postMessage 、 MessageChannel
注意: 下面的题目都是执行在浏览器环境下
遇到不好理解的,可结合 promise 源码 进行理解,就很简单了
解析:
解析:
解析:
解析:
解析:
解析:
解析:
解析:
现在看,本题就很简单了
解析:
详解如何构建Promise队列实现异步函数顺序执行
场景
有a、b、c三个异步任务,要求必须先执行a,再执行b,最后执行c
且下一次任务必须要拿到上一次任务执行的结果,才能做操作
思路
我们需要实现一个队列,将这些异步函数添加进队列并且管理它们的执行,队列具有First In First Out的特性,也就是先添加进去的会被先执行,接着才会执行下一个(注意跟栈作区别)
大家也可以类比一下jQuery的animate方法,添加多个动画也会按顺序执行
解决
模拟3个异步函数
// 异步函数a
var a = function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(’a’)
}, 1000)
})
}
// 异步函数b
var b = function (data) {
return new Promise(function (resolve, reject) {
resolve(data + ’b’)
})
}
// 异步函数c
var c = function (data) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(data + ’c’)
}, 500)
})
}
解决方法一(使用then链式操作)
特点:可以满足需求,但是书写比较繁琐
代码
//链式调用
a()
.then(function (data) {
return b(data)
})
.then(function (data) {
return c(data)
})
.then(function (data) {
console.log(data)// abc
})
方法二(构建队列)
特点:封装方法,可移植到别处使用
代码
// 构建队列
function queue(arr) {
var sequence = Promise.resolve()
arr.forEach(function (item) {
sequence = sequence.then(item)
})
return sequence
}
// 执行队列
queue()
.then(data =》 {
console.log(data)// abc
})
方法三(使用async、await构建队列)
同方法二,只是显得更高大上点
代码
async function queue(arr) {
let res = null
for (let promise of arr) {
res = await promise(res)
}
return await res
}
queue()
.then(data =》 {
console.log(data)// abc
})
顺便说一句,bluebird的Promise.reduce也可以用来顺序执行函数,但是可使用的场景非常有限,一般用来读取文件信息,而以上给出的方法,不管你在异步函数中做了什么,只要函数最后返回了一个Promise对象,都可以使用
Promise简书
promise是什么?
1、主要用于异步计算
2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
3、可以在对象之间传递和操作promise,帮助我们处理队列
为什么会有promise?
为了避免界面冻结(任务)
同步:假设你去了一家饭店,找个位置,叫来服务员,这个时候服务员对你说,对不起我是“同步”服务员,我要服务完这张桌子才能招呼你。那桌客人明明已经吃上了,你只是想要个菜单,这么小的动作,服务员却要你等到别人的一个大动作完成之后,才能再来招呼你,这个便是同步的问题:也就是“顺序交付的工作1234,必须按照1234的顺序完成”。
异步:则是将耗时很长的A交付的工作交给系统之后,就去继续做B交付的工作,。等到系统完成了前面的工作之后,再通过回调或者事件,继续做A剩下的工作。
AB工作的完成顺序,和交付他们的时间顺序无关,所以叫“异步”。
resolve作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
1、pending初始状态
2、fulfilled操作成功
3、rejected操作失败
当promise状态发生改变,就会触发then()里的响应函数处理后续步骤;
promise状态一经改变,不会再变。
Promise对象的状态改变,只有两种可能:
从pending变为fulfilled
从pending变为rejected。
这两种情况只要发生,状态就凝固了,不会再变了
1.Promise.all() 批量执行
Promise.all()用于将多个promise实例,包装成一个新的Promise实例,返回的实例就是普通的promise
它接收一个数组作为参数
数组里可以是Promise对象,也可以是别的值,只有Promise会等待状态改变
当所有的子Promise都完成,该Promise完成,返回值是全部值得数组
有任何一个失败,该Promise失败,返回值是第一个失败的子Promise结果
常见用法:
异步操作和定时器放在一起,,如果定时器先触发,就认为超时,告知用户;
例如我们要从远程的服务家在资源如果5000ms还没有加载过来我们就告知用户加载失败
2.Promise.race()
与 Promise.all 类似,但只等待第一个 settled 的 promise 并获取其结果(或 error)。
3.Promise.allSettled()
等待所有的 promise 都被 settle,无论结果如何。结果数组具有:
4.Promise.resolve()
Promise.resolve(value) 用结果 value 创建一个 resolved 的 promise。
5.Promise.reject()
Promise.reject(value) 用结果 value 创建一个 rejected 的 promise。
现实中的用法
回调包装成Promise,他有两个显而易见的好处:
1、可读性好
2、返回 的结果可以加入任何Promise队列
***隐藏网址***
***隐藏网址***

更多文章:
excel滚动条怎么调出来(怎么让excel表格显示出滚动条)
2025年11月4日 02:30
电脑网速慢怎么解决 教你优化电脑网络速度的方法?网络优化是怎么回事
2025年11月10日 12:15
take for granted(take for granted是什么意思)
2025年10月21日 02:45
虚拟机安装hadoop步骤(安装hadoop 中vi命令怎么用)
2025年10月28日 10:45
continue语句在循环体中的作用(c语言中continue语句的作用)
2025年9月3日 16:45
wsdl url is not valid(php如何处理wsdl)
2026年3月9日 20:30
字符串长度可以用lenngtn吗js(js中 我在一个函数中定义一个变量赋为值空!)
2025年7月14日 15:45
min height threshold(div固定一个高度,但内容多了又想让div随内容的变化而变化,怎么解决)
2026年1月6日 11:30
git pull和git clone(git的远程分支是干啥的,和本地的有什么区别)
2025年11月24日 03:15
abap开发工程师要懂什么技术(软件开发人员主要做什么工作)
2026年2月25日 10:45














