(JavaScript)Promise、消费者:then,catch,finally

Promise

  • 生产者代码:会做一些事情,并且需要一些时间
  • 消费者代码:想要在生产者代码完成工作的第一时间获得其工作成果。
  • Promise是将生产者代码和消费者代码连接在一起的一个特殊的对象。在生产者准备好时,将结果向所有消费者开放

Promise对象的构造器语法
let promise = new Promise(function(resolve, reject) {
  // executor(生产者代码)
});
  • resolve(value) — 如果任务成功完成并带有结果 value。
  • reject(error) — 如果出现了 error,error 即为 error 对象。
  • executor 会自动运行并尝试执行一项工作。尝试结束后,如果成功则调用 resolve,如果出现 error 则调用 reject。
    在这里插入图片描述

let promise = new Promise(function(resolve, reject) {
  // 当 promise 被构造完成时,自动执行此函数

  // 1 秒后发出工作已经被完成的信号,并带有结果 "done"(error)
  setTimeout(() => resolve("done"), 1000);
  //setTimeout(() => reject(new Error("Whoops!")), 1000);
});
  • executor通过new Promise被自动调用
  • executor 接受两个参数:resolve 和 reject。这些函数由 JavaScipt 引擎预先定义,因此我们不需要创建它们
  • 经过1s的处理,executor 调用 resolve(“done”) 来产生结果。这将改变 promise 对象的状态
    在这里插入图片描述在这里插入图片描述

只能有一个结果或一个error

executor 只能调用一个 resolve 或一个 reject。所有其他的再对 resolve 和 reject 的调用都会被忽略:

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

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

以 Error 对象 reject

reject(new Error("..."))中可以使用任何参数来完成,但建议使用Error对象


Resolve/reject 可以立即进行

executor 通常是异步执行某些操作,并在一段时间后调用 resolve/reject,但这不是必须的。我们还可以立即调用 resolvereject

let promise = new Promise(function(resolve, reject) {
  // 不花时间去做这项工作
  resolve(123); // 立即给出结果:123
});

state 和 result 都是内部的

Promise 对象的 stateresult 属性都是内部的。我们无法直接访问它们。但我们可以对它们使用 .then/.catch/.finally 方法。


消费者:then,catch,finally

  • 消费函数接受结果error。可以通过使用.then、.catch 和 .finally 方法为消费函数进行注册。

then

语法:

promise.then(
  function(result) { /* handle a successful result */ },
  function(error) { /* handle an error */ }
);
  • .then 的第一个参数是一个函数,该函数将在 promise resolved 后运行并接收结果
  • .then 的第二个参数也是一个函数,该函数将在 promise rejected 后运行并接收 error
let promise = new Promise(function(resolve, reject) {
  setTimeout(() => resolve("done!"), 1000);
  //setTimeout(() => reject(new Error("Whoops!")), 1000);
});

promise.then(
  result => alert(result), // 1 秒后显示 "done!"
  error => alert(error) // 不运行
  //result => alert(result), // 不运行
  //error => alert(error) // 1 秒后显示 "Error: Whoops!"
);

如果我们只对成功完成的情况感兴趣,那么我们可以只为.then提供一个函数参数

let promise = new Promise(resolve => {
  setTimeout(() => resolve("done!"), 1000);
});

promise.then(alert); // 1 秒后显示 "done!"

catch

如果我们只对error感兴趣:

  • 我们可以使用null作为第一个参数.then(null, errorHandlingFunction)
  • 也可以使用.catch(errorHandlingFunction)
let promise = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error("Whoops!")), 1000);
});

// .catch(f) 与 promise.then(null, f) 一样
promise.catch(alert); // 1 秒后显示 "Error: Whoops!"

finally
  • promise中也有finally,finally总是在promise被settled时运行:即promise被resolve或reject。
  • .finally(f) 调用与 .then(f, f) 类似
  • promise是执行清理很好的处理程序
new Promise((resolve, reject) => {
  /* 做一些需要时间的事儿,然后调用 resolve/reject */
})
  // 在 promise 为 settled 时运行,无论成功与否
  .finally(() => stop loading indicator)
  // 所以,加载指示器(loading indicator)始终会在我们处理结果/错误之前停止
  .then(result => show result, err => show error)
  • finally 处理程序(handler)没有参数。在 finally 中,我们不知道 promise 是否成功。
  • finally 处理程序将结果和 error 传递给下一个处理程序。
    例如,在这儿结果被从 finally 传递给了 then:
new Promise((resolve, reject) => {
  setTimeout(() => resolve("result"), 2000)
})
  .finally(() => alert("Promise ready"))
  .then(result => alert(result)); // <-- .then 对结果进行处理
  • 在这儿,promise 中有一个 error,这个 error 被从 finally 传递给了 catch:
new Promise((resolve, reject) => {
  throw new Error("error");
})
  .finally(() => alert("Promise ready"))
  .catch(err => alert(err));  // <-- .catch 对 error 对象进行处理
  • 因为 finally 并不是意味着要处理 promise 的结果。所以它将结果传递了下去。

  • 如果 promise 为 pending 状态,.then/catch/finally 处理程序(handler)将等待它。否则,如果 promise 已经是 settled 状态,它们就会运行:
// 下面这 promise 在被创建后立即变为 resolved 状态
let promise = new Promise(resolve => resolve("done!"));

promise.then(alert); // done!(现在显示)

示例: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 => alert(`${script.src} is loaded!`),
  error => alert(`Error: ${error.message}`)
);

promise.then(script => alert('Another handler...'));

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值