[JS] You Don't Know JavaScript [Async & Performance] - Promises

前言

在上一张中我们介绍了使用callback function的目的与缺点,虽然可以帮助我们处理非同步问题,但缺乏顺序性可靠性,这时人们想着:能不能有一个"在当前任务完成後才要发生的事",不会造成顺序变化?并且可能返回这个非同步任务是成功还是失败。

於是乎Promise就这麽诞生了,而Promise代表为一个容器,保存着某个未来才会结束的事件(非同步)的结果,它他可以像同步事件一样返回结果,可以返回以解决的值或是未解决的原因并且无法更改结果。

这看起来似乎是个美妙的东西,不仅可以解决头痛的非同步问题还可以避免掉callback function的缺点,让我们仔细的介绍一下这个神奇的方法。
https://ithelp.ithome.com.tw/upload/images/20210119/20124767coqYsE1FsY.png


What is Promise?

Promise是一个存放着非同步事件的结果,可以回传成功的结果或未成功的原因。

这句话虽然可以解释Promise是什麽,但是可能对於刚接触或是对JS不熟的朋友们还是有点难度,让我换一个说法:

想像一下你今天去麦当劳点了一个大麦克、劲辣鸡腿堡、蕈菇安格斯黑牛堡再加点四块麦克鸡块,汉堡都搭配套餐薯条可乐(太多了...),虽然店员会一脸疑惑地觉得你真的吃得下吗,但是他还是会给你一个号码牌,而这个号码牌就代表着JavaScript的Promise。

你可以那着这个号码牌到旁边一边滑手机一边等餐,而这就是非同步事件,而你在滑手机的时候不会担心你的餐点不见,因为你拿到了你的号码牌(当然还是因为你付钱了...),这就是一个Promise一个承诺,承诺会给你一个结果

但是也有另一种可能,当柜台叫到你的号码时你满心期待的到柜台想拿到你的餐点,但是他们跟你说由於刚刚柜台不知道厨房备料的状况,所以你的餐点卖光了无法给你并把钱退还给你,这就是Promise的另一个重点,如果失败了他会告诉你他失败了并把失败的原因告诉你不会让你在旁边痴痴的等,这就是Promise的概念。


How Promises Work?

Promise是一个Object他会有三种状况:

  1. Pending: 成功或失败前的初始状态。
  2. Resolved: 事件成功。
  3. Rejected: 事件失败。

https://ithelp.ithome.com.tw/upload/images/20210119/20124767VvxXize7eF.png
(图片来源:JavaScript Promise Tutorial: Resolve, Reject, and Chaining in JS and ES6

举个例子,当我们使用Promise向服务器请求後端数据,他会先进到Pending状态,因为还在处理尚未得到数据或是失败,而这个状态持续到我们得到结果为止。

如果我们成功获得後端的数据,则Promise从Pending变为Resolved代表事件成功,相反的如果没有获得数据则从Pending变为Rejected代表事件失败,无论是事件完成或是失败都会在回传一个Promise让我们链接新的事件在後面。

一旦Promise的状态发生改变就无法更改,Promise结果的不变性是非常重要的。


Error Handling

Promise有自己的错误处理机制,这对我们编写非同步程序来说是非常重要的,由於非同步事件的特性会让我们对非同步事件的结果不好掌握常常会造成不可与其的错误,需要加上许多判断式来确保我们的非同步事件的确定性,但Promise可以很有效的帮我们解决这个问题。

then可以接收两个callback function参数,一个是代表Promise成功反之代表失败。

let promise = Promise.reject(new Error('This is reject'));

function resolved(result){
    console.log('Resolved');
}
function rejected(err){
    console.log(err);
}

promise.then(resolved, rejected); // This is reject

虽然上面这种写法可以在我们promise失败时捕获到错误,但是如果当promise成功进到resolved後却在resolved中发生错误,而这个错误将会被忽略。
https://ithelp.ithome.com.tw/upload/images/20210119/20124767DSQFhGM21h.png
(图片来源:Master the JavaScript Interview: What is a Promise?

於是Promise提供了另一种写法。

let promise = Promise.reject(new Error('This is reject'));

function resolved(result){
    console.log('Resolved');
}
function rejected(err){
    console.log(err);
}

promise.then(resolved).catch(rejected); // this is resolve

这种写法可以使catch捕获到promise或resolved的错误。
https://ithelp.ithome.com.tw/upload/images/20210119/20124767GzFH9lYURQ.png
(图片来源:Master the JavaScript Interview: What is a Promise?


Terminology: Resolve, Fulfill, and Reject

在更深入的了解Promise之前,我们需要先了解resolve、fulfill和reject之间的区别。

  • Promise.resolve:会返回一个给定值的Promise Objcet,他一定会使Promise状态从pending变为Resolved并可以使用then获取得订得值。
let promise = Promise.resolve('this is resolve');

promise.then(val => console.log(val)); // this is resolve
  • Promise.reject:会返回一个Promise Objcet,他一定会使Promise状态从pending变为Rejected并可以使用catch获得错误内容。
let promise = Promise.reject(new Error('This is reject'));

promise.catch(err => console.log(err)); // This is reject

function resolved(result){
    console.log('Resolved');
}
function rejected(err){
    console.log(err);
}

promise.then(resolved, rejected); // This is reject

参考文献

You Don't Know JavaScript
Promise
Master the JavaScript Interview: What is a Promise?


<<:  菜鸡的学习笔记 终於开始了!

>>:  ​修复:隐藏受保护的作业系统档案选项在资料夹选项中丢失

【Day 10】- 你的爬虫是哪一类的? (网路爬虫的类型)

前情提要 前一篇文章带大家看了 BeautifulSoup 库的使用,用他来做资料清洗,使我们真正想...

Day 0xC - Debug 地狱第三天,终於逃脱了 (建立订单)

0x1 前言 从 Day 0xA 开始撞墙,撞到今天总算解出来了 几个问题请让我娓娓道来 0x2 好...

30天零负担轻松学会制作APP介面及设计【DAY 30】

大家好,我是YIYI,今天我要来打完赛心得啦。 时间真的过得好快呀~不知不觉就到30天了呢。 一开始...

[第五只羊] 迷雾森林建筑工事 IV 专案环境设定 READY GO

天亮了 昨晚是平安夜 关於迷雾森林故事 小狼现身请睁眼 待洛神解释完了迷雾森林的由来 知悉了 ani...

#2 HTML x Lovely Auntie

What is HTML? English: Wiki - HTML Mandarin: HTML ...