实现 Promise

想要实现基于 promise 的 API ,我们可以使用事件、普通回调或者消息传递模型来包裹一个异步操作。使用 Promise 对象可以合理的处理操作的成功或者失败。

实现 alarm() API

实现一个基于 promise 的 alarm API,叫做 alarm() 。接受两个参数,一个是 人名 ,一个是 延迟时间 。在延迟之后,函数会发送一个包含人名的 “Wake up!” 消息。

用 setTimeout() 包裹

用 setTimeout() 来实现 alarm() 函数。

setTimeout() 接受两个参数,一个是回调函数,一个是延迟时间,当调用 setTimeout() 时,将启动一个设置为给定延迟时间的延迟计时器,当时间过期,即刻调用回调函数。

<button id="set-alarm">Set alarm</button>
<div id="output"></div>
const output = document.querySelector("#output");
const button = document.querySelector("#set-alarm");

function setAlarm() {
  window.setTimeout(() => {
    output.textContent = "Wake up!";
  }, 1000);
}

button.addEventListener("click", setAlarm);

控制台输出效果:

Wake up!

Promise() 构造器

设置一个 alarm() 函数返回一个在定时器过期时才会被兑现的 Promise。传递一个 “Wake up!” 消息到 then() 处理器中,也会在当调用者提供一个负延迟值时拒绝这个 promise。

这里的关键组件是 Promise() 构造器。Promise() 构造器使用单个函数作为参数。我们把这个函数称作执行器(executor)。当你创建一个新的 promise 的时候你需要实现这个执行器。

这个执行器接收两个参数,这两个参数都是函数,通常被称作 resolve 和 reject。在执行器实现里,调用原始的异步函数。如果异步函数成功了,就调用 resolve,如果失败了,就调用 reject。如果执行器函数抛出了一个错误,reject 会被自动调用。你可以将任何类型的单个参数传递到 resolve 和 reject 中。

function alarm(person, delay) {
  return new Promise((resolve, reject) => {
    if (delay < 0) {
      throw new Error("Alarm delay must not be negative");
    }
    window.setTimeout(() => {
      resolve(`Wake up, ${person}!`);
    }, delay);
  });
}

此函数创建并且返回一个新的 Promise。对于执行器中的 promise,我们:

  • 检查 delay(延迟)是否为负数,如果是的话就抛出一个错误。
  • 调用 window.setTimeout(),传递一个回调函数和 delay(延迟)。当计时器过期时回调会被调用,在回调函数内,我们调用了 resolve,并且传递了 “Wake up!” 消息。

使用 alarm() API

调用 alarm(),在返回的 promise 中调用 then() 和 catch() 来设置 promise 兑现和拒绝状态的处理器。

const name = document.querySelector("#name");
const delay = document.querySelector("#delay");
const button = document.querySelector("#set-alarm");
const output = document.querySelector("#output");

function alarm(person, delay) {
  return new Promise((resolve, reject) => {
    if (delay < 0) {
      throw new Error("Alarm delay must not be negative");
    }
    window.setTimeout(() => {
      resolve(`Wake up, ${person}!`);
    }, delay);
  });
}

button.addEventListener("click", () => {
  alarm(name.value, delay.value)
    .then((message) => (output.textContent = message))
    .catch((error) => (output.textContent = `Couldn't set alarm: ${error}`));
});

控制台输出:

正常:Wake up, Matilda!
给 Delay 设置负值: Couldn’t set alarm: Error: Alarm delay must not be negative

在 alarm() API 上使用 async 和 await

alarm() 返回了一个 Promise ,即可实现全部 Promise 的功能:Promise.all(),和 async / await:

const name = document.querySelector("#name");
const delay = document.querySelector("#delay");
const button = document.querySelector("#set-alarm");
const output = document.querySelector("#output");

function alarm(person, delay) {
  return new Promise((resolve, reject) => {
    if (delay < 0) {
      throw new Error("Alarm delay must not be negative");
    }
    window.setTimeout(() => {
      resolve(`Wake up, ${person}!`);
    }, delay);
  });
}

button.addEventListener("click", async () => {
  try {
    const message = await alarm(name.value, delay.value);
    output.textContent = message;
  } catch (error) {
    output.textContent = `Couldn't set alarm: ${error}`;
  }
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值