【慕课网】Promise 入门教程
警告
本文最后更新于 2020-03-02,文中内容可能已过时。
讲师:翟路佳 课程:https://www.imooc.com/learn/949 代码:https://github.com/merrier/imooc-promise-sample
第一章 异步的问题
1-1 课程介绍
- 了解 Promise 诞生的历史背景
- 学会使用 Promise 解决异步回调带来的问题
- 掌握 Promise 的进阶用法
1-2 Promise 释义
按照用途来解释
- 主要用于异步计算
- 可以将异步操作队列化,按照期望的顺序执行,返回复合预期的结果。
- 可以在对象之间传递和操作 Promise,帮助我们处理队列。
1-3 异步产生的原因
- JavaScript 包含大量异步操作
- 有了 Node.js 之后,对异步的依赖进一步加剧了(无阻塞高并发,是 Node.js 的招牌;异步操作是其保障;大量操作依赖回调函数)
异步操作的常见语法
- 事件侦听与相应
- 回调
1-4 异步回调的问题
- 不好维护
- 异步回调函数会在一个新的栈运行,所以无法获取之前的栈的信息;之前的栈也无法捕获这个栈抛出的错误信息。所以没法正常使用 try catch
总结如下
- 嵌套层次很深,难以维护
- 无法正常使用 return 和 throw
- 无法正常检索堆栈信息
- 多个回调之间难以建立联系
第二章 Promise 入门
2-1 Promise 简介
使用之前,初始化 Promise 实例
new Promise(
/* 执行器executor */
function (resolve, reject) {
//一段耗时很长的异步操作
resolve(); //数据处理完成
reject(); //数据处理出错
}
).then(
function A() {
//调用resolve()成功,下一步
},
function B() {
//调用reject()或抛出错误,做相应处理
}
);
Promise 详解
- Promise 是一个代理对象,它和原先要执行的操作并无关系。
- 它通过引入一个回调,避免更多的回调。
- Promise 有三个状态:
- pending[待定]初始状态
- fulfilled[实现]操作成功
- rejected[被否决]操作失败
- Promise 状态发生改变,就会触发.then()里的响应函数处理后续步骤。
- Promise 状态一经改变,不会再变。
- Promise 实例一经创建,执行器立即执行。
2-2 最简单的实例
timeout.js
2-3 两步执行的范例
timeout2.js
2-4 对已完成的 Promise 执行 then
fulfilled-then.js 在任何地方生成一个 Promise 队列后,可以把它作为一个变量传递到其他地方,不管前面 Promise 队列是否完成,队列都会按照追加的 then 来执行。
2-5 then 里不返回 Promise
timeout3.js 在 Promise 里,如果不直接返回一个 Promise 实例,那么它就会默认执行下一个环节,即使返回了 false,也不影响下一步,因为 false 会直接传递到下一环节里;如果没有明确返回值,相当于返回 undefined
2-6 引出.then()
- .then()接受两个函数作为参数,分别代表 fulfilled 状态下的响应函数和 rejected 状态下的响应函数。
- .then()返回一个新的 Promise 实例,所以它可以链式调用。
- 当前面的 Promise 状态改变时,.then()根据其最终状态,选择特定的状态响应函数执行。
- 状态响应函数可以返回新的 Promise,或其它值
- 如果返回新的 Promise,那么下一级.then()会在新 Promise 状态改变之后执行。
- 如果返回其它任何值,则会立刻执行下一级.then()。
第三章 小测试
3-1 then 的嵌套
nested-then.js .then()里有.then()的情况
- 因为.then()返回的还是 Promise 实例
- 会等里面的.then()执行完,再执行外面的
- 最好将其展开,会更好读
3-2 随堂小测试
问题:下面的四种 Promise 的区别是什么
//# 1
doSomething()
.then(function () {
return doSomethingElse();
})
.then(finalHandler);
执行顺序:
doSomething |
---|
doSomethingElse(undefined) |
– |
finalHandler(resultOfDoSomthingElse) |
– |
//#2
doSomething()
.then(function () {
doSomethingElse();
})
.then(finalHandler);
执行顺序:
doSomething |
---|
doSomethingElse(undefined) |
– |
finalHandler(resultOfDoSomthingElse) |
– |
//#3
doSomething().then(doSomethingElse()).then(finalHandler);
执行顺序:
doSomething |
---|
doSomethingElse(undefined) |
– |
finalHandle(resultOfDoSomething) |
– |
//#4
doSomething().then(doSomethingElse).then(finalHandler);
执行顺序:
doSomething |
---|
doSomethingElse(resultOfDoSomething) |
– |
finalHandler(resultOfDoSomethingElse) |
– |
3-3 错误处理
error.js error-reject.js Promise 会自动捕获内部异常,并交给 rejected 响应函数处理。
错误处理的两种做法
- reject(‘错误信息’).then(null,message=>{})
- throw new Error(‘错误信息’).catch(message=>{})
- 推荐使用第二种,更加清晰好读,并且可以捕获前面的错误。
3-4 错误和 then 连用
catch-then.js catch 也会返回一个 Promise 实例,并且其中没有抛出错误的话,它返回的 Promise 实例是 fulfilled 状态的
注意
- 强烈建议在所有队列最后都加上.catch(),以避免漏掉错误处理造成意想不到的问题。
第四章 Promise 进阶
4-1 Promise.all
批量执行
- Promise.all([p1,p2,p3,……])用于将多个 Promise 实例,包装成一个新的 Promise 实例
- 返回的实例是一个新的普通的 Promise
- 它接受一个数组作为参数
- 数组里可以是 Promise 对象,也可以是别的值,只有 Promise 会等待状态改变
- 当所有子 Promise 都完成,该 Promise 完成,返回值是全部值的数组
- 任何一个失败,该 Promise 失败,返回值是第一个失败的子 Promise 的结果 详见 all.js
4-2 与.map 连用
Promise.all()最常见就是和.map()连用 map.js