消费者怎么看待 then, catch, finally

人生代码

共 3344字,需浏览 7分钟

 ·

2021-02-11 10:13

消费者:then,catch,finally

昨天讲了关于 Promise 的理解,有人在下面评论说要我出关于源码的解析,能力有限只能循序渐进了,我们还是先把基础的搞明白,再逐步深入。

Promise对象充当执行者(“产生代码”或“singer”)和消费函数(“fans”)之间的链接,它们将接收结果或错误。使用.then、.catch和.finally方法可以注册(订阅)消费函数。

then

最重要,最基本的是 then 。

他的的语法是:

promise.then(
  function(result/* handle a successful result */ },
  function(error/* handle an error */ }
);

then的第一个参数是一个函数,它在promise被解析时运行,并接收结果。

then的第二个参数是一个函数,当promise被拒绝时运行,并接收错误。

例如,以下是人们对成功解决的反应:

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

// resolve runs the first function in .then
promise.then(
  result => alert(result), // shows "done!" after 1 second
  error => alert(error) // doesn't run
);

执行了第一个函数。

在被拒绝的情况下,第二个

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

// reject runs the second function in .then
promise.then(
  result => alert(result), // doesn't run
  error => alert(error) // shows "Error: Whoops!" after 1 second
);

如果我们只对成功完成感兴趣,那么我们只能为.then提供一个函数参数:

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

promise.then(alert); // shows "done!" after 1 second

catch

如果我们只对错误感兴趣,那么可以使用null作为第一个参数:.then(null, errorHandlingFunction)。或者我们可以使用.catch(errorHandlingFunction),两者完全相同:

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

// .catch(f) is the same as promise.then(null, f)
promise.catch(alert); // shows "Error: Whoops!" after 1 second

调用.catch(f)完全是对.then(null, f)的模拟,它只是一个简写。

finally

就像在一个普通的try{…} catch{…}终于有了承诺。

调用.finally(f)类似于.then(f, f),因为f总是在promise被解决时运行:无论是resolve还是reject。

finally是一个很好的处理程序,用于执行清理,例如停止我们的加载指示器,因为它们不再需要了,无论结果是什么。

是这样的:

new Promise((resolve, reject) => {
  /* do something that takes time, and then call resolve/reject */
})
  // runs when the promise is settled, doesn't matter successfully or not
  .finally(() => stop loading indicator)
  // so the loading indicator is always stopped before we process the result/error
  .then(result => show result, err => show error)

也就是说,finally(f)并不是then(f,f)的别名。有一些细微的区别:

finally处理程序没有参数。在最后,我们不知道诺言是否成功。没关系,因为我们的任务通常是执行“一般的”收尾过程。

finally处理程序将结果和错误传递给下一个处理程序。

例如,这里的结果被传递给finally:

new Promise((resolve, reject) => {
  setTimeout(() => resolve("result"), 2000)
})
  .finally(() => alert("Promise ready"))
  .then(result => alert(result)); // <-- .then handles the result

在promise中有一个错误,最后传递给catch:

new Promise((resolve, reject) => {
  throw new Error("error");
})
  .finally(() => alert("Promise ready"))
  .catch(err => alert(err));  // <-- .catch handles the error object

例子:loadScript

我们在前一章中使用了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 重写一下。

新的函数loadScript不需要回调。相反,它将创建并返回一个Promise对象,该对象将在加载完成时解析。外部代码可以使用.then向其添加处理程序(订阅函数):

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...'));


浏览 41
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报