初识JavaScript的Promise

392 阅读3分钟

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

前言

在开始promise之前,我们先来了解两个后面要用到的词

  • 生产者代码(producing code):会做一些事儿,并且会需要一些时间的代码。例如,通过网络加载数据的代码。

  • 消费者代码(consuming code):想要在“生产者代码”完成工作的第一时间就能获得其工作成果的代码

我们要说的Promise 就是将“生产者代码”和“消费者代码”连接在一起的一个特殊的 JavaScript 对象。

👉 相关内容:说说JavaScript里的回调函数

基本概念

Promise 对象的构造器(constructor)语法

let promise = new Promise(function(resolve, reject) {
  // executor(生产者代码)
});

传递给 new Promise 的函数被称为 executor

executor 会自动运行并尝试执行一项工作。尝试结束后,如果成功则调用 resolve,如果出现 error 则调用 reject

  • resolve(value) — 如果任务成功完成并带有结果 value
  • reject(error) — 如果出现了 error,error 即为 error 对象。

promise 对象内部属性

new Promise 构造器返回的 promise 对象具有以下内部属性:

  • state — 最初是 "pending",然后在 resolve 被调用时变为 "fulfilled"(已兑现),或者在 reject 被调用时变为 "rejected"(已拒绝)。

image-20211123000820726

  • result — 最初是 undefined,然后在 resolve(value) 被调用时变为 value,或者在 reject(error) 被调用时变为 error

image-20211123000916621

🎨 成功示例

let promise = new Promise(function(resolve, reject) {
  setTimeout(() => resolve("done"), 1000);   //成功
});

💡 代码分析:以上示例中, 当 promise 被构造完成时,会自动执行setTimeout函数,1 秒后发出工作已经被完成的信号,改变 promise 对象的状态并带有结果 "done";

state: "fulfilled" result: "done"

image-20211123001843042

🎨 失败示例

let promise = new Promise(function(resolve, reject) { 
  setTimeout(() => reject(new Error("Whoops!")), 1000);  //失败
});

💡 代码分析:以上示例中, 当 promise 被构造完成时,会自动执行setTimeout函数, 1 秒后发出工作已经被完成的信号,并带有 error

state: "rejected" result: error

image-20211123002119475

注意

1、【💥】executor 只能调用一个 resolve 或一个 reject,如果调用多个,后面的会被忽略

let promise = new Promise(function(resolve, reject) {
  resolve("done");

  reject(new Error("…")); // 被忽略
  setTimeout(() => resolve("…")); // 被忽略
});

2、resolve/reject 只需要一个参数(或不包含任何参数),并且将忽略额外的参数。

3、state result 都是内部的,无法直接访问,但可以对它们使用 .then/.catch/.finally 方法。

消费者 .then

Promise 对象充当的是 executor(“生产者代码”)和消费函数之间的连接,后者将接收结果或 error。可以通过使用 .then 方法为消费函数进行注册。

📖 语法:

promise.then(
  function(result) { /* 成功 */ },
  function(error) { /* 失败 */ }
);

💡 说明:

.then 的第一个参数是一个函数,该函数将在 promise resolved 后运行并接收结果。

.then 的第二个参数也是一个函数,该函数将在 promise rejected 后运行并接收 error。

🎨 示例1

关键代码:resolve("done!")

image-20211123003238971

🎨 示例2

关键代码:reject(new Error("Whoops!"))

image-20211123003347775

改写

之前说回调的时候,我们写了一个加载脚本的 loadScript 函数,是这样的

function loadScript(src, callback) {
  let script = document.createElement('script');
  script.src = src;

  script.onload = () => callback(null, script);
  script.onerror = () => callback(new Error(`Script load error for ${src}`));

  document.head.append(script);
}

现在用 promise 重写

function loadScript(src) {
  return new Promise(function(resolve, reject) {
    let script = document.createElement('script');
    script.src = src;

    script.onload = () => resolve(script);
    script.onerror = () => reject(new Error(`Script load error for ${src}`));

    document.head.append(script);
  });
}

🍒 用法:

let  promise
=  loadScript("https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js");

promise.then(
  script => console.log(`${script.src} is loaded!`),
  error => console.log(`Error: ${error.message}`)
);

参考资料:

JavaScript Promise basics

MDN Promise

Using Promises


🎨【点赞】【关注】不迷路,更多前端干货等你解锁

往期推荐

👉 一起来看看JS的原型继承

👉 JS中的getter和setter你会用吗?

👉 深入理解ES6箭头对象

👉 JS的装饰器模式实例分析