Promise

前言

不知道大家学习英语的时候有没有过明明语法规则都记清楚了,却还是不清楚实际如何运用的经验,或是只能死记文法书上的句子,遇到变化的情形就不知所措(怎麽好像是要卖英文课程XD

上述的经验想必大家或多或少都曾经历过,而我在学习 Promise 的时候也有同样的感受。/images/emoticon/emoticon06.gif

以下尝试在认识语法後,用生活实例练习 Promise 的概念

语法与观念

在蹲马步学习语法前,必须要知道 Promise 的出现是因为过去用callback 方式来处理非同步事件的顺序时,程序码会有过於巢状难以阅读及难维护的现象

Promise的串接特性让原本多层巢状的程序码可以变成单层

而在 ES2017 (ES8) 又出现了async/await,整个演化史简单呈现如下:

callback hell --> Promise --> async/await

知道整个脉络後一起来看语法吧!

new Promise( /* executor */ function(resolve, reject) { ... } );

根据MDN的语法规则,Promise 物件接受一个callback function,这个 callback function 接受两个参数:

  1. resolve 函式
  2. reject 函式

Promise 物件会有以下几种状态:

  1. pending:初始状态,不是 fulfilled 与 rejected。
  2. fulfilled:表示操作成功完成。
  3. rejected:表示操作失败


图片来源:MDN

根据上图,Promise物件在建立时是处於 pending 的状态,之後会有以下两种可能:

  1. 成功 --> 执行 resolve 函式 --> 状态由 pending 变成 fulfilled
  2. 发生错误 --> 执行 reject 函式 --> 状态由 pending 变成 rejected

promise 方法

这两个方法都可以回传 Promise,可以继续串接。

  • Promise.prototype.then():接收 resolve 函式的结果
  • Promise.prototype.catch():用来抓取 reject 函式的错误原因

日常实例练习

看完语法觉得一切支离破碎的话不如一起跟着生活实例练习看看~(以下范例参考 Wes Bos 部落格改写)

想像我们今天去点饮料,店家会给你收据和叫号单,当号码轮到你的时候才代表饮料做好了,Promise 的概念就类似於那张叫号单,当我们拿到叫号单的时候,代表我们在未来某一刻会拿到点的饮料。

以下在makeDrinks的函式中回传一个 Promise,用 setTimeout 模拟等待店家制作饮料的时间。

function makeDrinks(drinksName) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`这是你点的${drinksName}`);
    }, 2000);
  });
}

// 一张叫号单
const bubbleTeaPromise = makeDrinks("珍珠奶茶");

console.log(bubbleTeaPromise); // 印出一个Promise物件


// 用.then() 取得结果
bubbleTeaPromise.then((drinks) => {
   console.log(drinks);
});

// 这是你点的珍珠奶茶

现在模拟店家收到三张订单,必须依照来电先後顺序制作

makeDrinks("珍珠奶茶")
  .then((drinks) => {
    console.log(drinks);
    return makeDrinks("英式红茶");
  })
  .then((drinks) => {
    console.log(drinks);
    return makeDrinks("美式咖啡");
  })
  .then((drinks) => {
    console.log(drinks);
  });
  
//这是你点的珍珠奶茶
//这是你点的英式红茶
//这是你点的美式咖啡

假设店家今天的招牌ironman冬瓜柠檬卖完了,店员便会取消订单,在程序码上增加了 reject 函式,如果有客人点了这个品项就会执行,Promise转为rejected状态,并执行 catch 流程

function makeDrinks(drinksName) {
  return new Promise((resolve, reject) => {
    if (drinksName.includes("ironman")) {
      reject("ironman冬瓜柠檬卖完了");
    }
    setTimeout(() => {
      resolve(`这是你点的${drinksName}`);
    }, 2000);
  });
}


makeDrinks("美式咖啡")
  .then((drinks) => {
    console.log(drinks);
    return makeDrinks("珍珠奶茶");
  })
  .then((drinks) => {
    console.log(drinks);
    return makeDrinks("ironman冬瓜柠檬");
  })
  .then((drinks) => {
    console.log(drinks);
  })
  .catch((err) => {
    console.log(err);
  });
  
  
//这是你点的美式咖啡
//这是你点的珍珠奶茶
//ironman冬瓜柠檬卖完了

结语

经过这次写文章学习,对於 Promise 的理解大约从 1.5% 提升到 55% 左右,期许之後理解程度可以再提升至 87%

如果有任何错误的地方也请高手们指教了,感谢~/images/emoticon/emoticon41.gif

参考资料:
MDN
Promises


<<:  [Day17] XML Signature Wrapping

>>:  2021-Day27. Serverless(十 五):Azure - 建立帐号 & 安装 IntelliJ IDEA 的 Azure Toolkit Plugins

[Day28] swift & kotlin 上架篇!(2) 小鸡BB-游戏上架流程-kotlin

Android 上架 首先~当然也是缴钱了 进入 Google Play Console 填入资料,...

矛盾睡眠的断面

回到家以後,沉睡又再沉睡的时间大量发生。 平常没有休息的部分,直接从所有内里涌现出来。 即使是平常很...

[神经机器翻译理论与实作] Google Translate的神奇武器- Seq2Seq (III)

前言 今天继续我们未完成的建模大业吧! 我们要建立的seq2seq模型由LSTM编码器与解码器串接而...

## Day28 LineBot models小介绍

在linebot之中有提供几种讯息格式, Location Imagemap Template 现在...

庄家 show hand 了? - 竭尽点 ?

今年是台股放量的一年,也是新一代韭菜毕业的一年 很多人提到无本当冲多好赚之类的 但当冲没看懂方向真的...