这篇文章会是参考这篇文章,并且浓缩出重点,最后也会有几题测验,方便验收学习状况,那么我们进入今天的文章: Promise
什么是 Promise?
Promise 通常会由 「生产者代码」(producing code) 跟 「消费者代码」(consuming code) 组成
生产者代码 (producing code)
通过网路加载数据的程式码,例如: 餐厅
消费者代码 (consuming code)
想要在"生产者代码"完成工作的第一时间就能获得其工作成果的程式码,例如: 顾客
生产者代码 - Promise 对象的构造器 (constructor)
let promise = new Promise(function(resolve, reject) { // executor});
传递给 new Promise
的函数被称为 executor
,executor
会在 new Promise
被创立时,自动执行
这边可以看到有 resolve
跟 reject
两个参数,分别代表成功或失败
new Promise
除了会有 result
(resolve 或是 reject),还有 state
,代表该 Promise 的执行状态
预设会是 pending
,resolve 被调用时变为 fulfilled
,或者在 reject 被调用时变为 rejected
。
任何一个 resolved
或 rejected
的 promise 都会被称为 settled
这只能有一个结果或一个 error
let promise = new Promise(function(resolve, reject) { resolve("done"); reject(new Error("…")); // 被忽略 setTimeout(() => resolve("…")); // 被忽略});
这边想说明的是不管是 resolve
还是 reject
,任何一个被触发后,就会跳脱出 Promise,所以后面的 resolve
或是 reject
,就会被省略掉
state 和 result 都是内部的
刚刚有提到的 state 和 result 都只存活在该 Promise 中,一但离开了 Promise ,将不复存在,不过我们可以透过 .then()
、.catch()
去接收 result
消费者代码
.then()
p.then(onFulfilled, onRejected);
.then()
接受两个参数,分别是 Promise 在成功及失败情况时的回呼函式。
let promise = new Promise(function(resolve, reject) { setTimeout(() => resolve("done!"), 1000);});promise.then( result => alert(result), error => alert(error));
.catch()
.catch()
只会抓取 错误 (reject) 的 result
如果只对于错误 result 有兴趣,有两种方法
p.then(null, errorHandlingFunction) // 将 onFulfilled 设定为 nullp..catch(errorHandlingFunction)
.finally()
finally
的功能是设置一个处理程式在前面的操作完成后,执行清理/终结。finally
的执行时间是在 promise settled
时就会执行:无论 promise 的result 是 resolve 还是 reject。
小试身手
这边分享四题我觉得还不错的考题,给各位读者做练习
请说明 console 出来的顺序const promise = new Promise((resolve, reject) => { console.log(1) resolve() console.log(2)})promise.then(() => { console.log(3)})console.log(4)
答案:
1 -> 2 -> 4 -> 3
原因是因为 Promise 构造函数是同步执行的,promise.then 中的函数是异步执行的
请说明 console 出来的顺序,这题比较常,不过感觉会是业界会考的题目const first = () => (new Promise((resolve, reject) => { console.log(3); let p = new Promise((resolve, reject) => { console.log(7); setTimeout(() => { console.log(5); resolve(6); }, 0) resolve(1); }); resolve(2); p.then((arg) => { console.log(arg); });}));first().then((arg) => { console.log(arg);});console.log(4);
答案:
3 -> 7 -> 4 -> 1 -> 2 -> 5
相信大家基本上都能答出 3 -> 7 -> 4 ,至于后面的 1 -> 2 -> 5 是因为 setTimeout 是一个 Macrotask 他会先被放到 task queue 中,等待 Microtask 都执行完成才会被丢到 call stack 中执行
如果不清楚 macrotask 跟 microtask 的读者,可以参考我之前的文章
const promise = new Promise((resolve, reject) => { resolve('success1') reject('error') resolve('success2')})promise .then((res) => { console.log('then: ', res) }) .catch((err) => { console.log('catch: ', err) })
答案:
then: success1
原因是因为 Promise 中的 resolve 或 reject 只有第一次执行有效,所以后面的都会被省略
4. 请问下方程式码会 console 出什么?
Promise.resolve(1) .then((res) => { console.log(res) return 2 }) .catch((err) => { return 3 }) .then((res) => { console.log(res) })
答案:
1 2
原因是因为 Promise 可以链式调用。
Promise 每次调用 .then 或者 .catch 都会返回一个新的 Promise,从而实现了链式调用。
至于不是 1 3 的原因是因为是 resolve
可以想像成
Promise.resolve(1) .then((res) => { console.log(res) return 2 })Promise.resolve(2) .then((res) => { console.log(res) })
以上就是今天 Promise 的介绍,文章最后还是推荐各位读者可以去看看JavaScript.info 的文章
文章同步发布在我的 Medium ,有兴趣的读者可以去看看
以上就是今天的文章,如果有任何错误,或是问题都欢迎留言给我,那我们下次见,掰掰
参考文章:
https://javascript.info/promise-basics
https://medium.com/@123davidbill/macrotask-vs-microtask-%E5%B8%B8%E6%90%9E%E9%8C%AF%E7%9A%84%E9%83%A8%E5%88%86-236b7c2b8e8b