JS Promise 的一些理解

JS Promise

简介

Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。(MDN的定义)

什么是 JS 的异步操作 ?

知乎上面的回答

为什么要使用Promise ?

解决“回调地狱”,使代码更加清晰、易于维护

举个例子,现在我需要通过src动态加载一个JS脚本

function loadScript(src) {
  // 创建一个 <script> 标签,并将其附加到页面
  // 这将使得具有给定 src 的脚本开始加载,并在加载完成后运行
  let script = document.createElement('script');
  script.src = src;
  document.head.append(script);
}

当然我希望了解脚本何时加载完成,以使用其中的新函数和变量。但是我在外部获取不到函数内部的变量,所以必须给给他加上一个回调函数。

function loadScript(src, callback) {
  let script = document.createElement("script");
  script.src = src;
  document.head.append(script);
  // 当脚本挂载成功后调用callback(null,script);
  script.onload = () => callback(null, script);
  // 当脚本挂载失败后调用callback(new Error(`Script load error for ${src}`));
  script.onerror = () => callback(new Error(`Script load error for ${src}`));
}

loadScript("./src.js", (error, script) => {
  if (error) { //处理error
    console.log(error);
  } else {
    console.log("success");
  }
});

当我需要继续依次加载多个脚本,那么代码会变成这样。

loadScript("./src.js", (error, script) => {
  if (error) {
    console.log(error);
  } else {
    loadScript("./src.js", (error, script) => {
      if (error) {
        console.log(error);
      } else {
        loadScript("./src.js", (error, script) => {
          if (error) {
            console.log(error);
          } else {
            console.log("success");
          }
        });
      }
    });
  }
});

代码会逐渐向右缩进,不利于维护和阅读。这就是我们所说的“回调地狱”。

Promise的基本使用

创建一个Promise对象

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

let promise = new Promise((resovle, reject) => {
  //executor(执行者)
})
  • 传递给 new Promise 的函数被称为 executor。当 new Promise 被创建,executor 会立刻自动运行。
  • 一个 Promise 对象有 PromiseState , PromiseResult 两个属性:
    • PromiseState (state)有三个状态:
      • pending: 初始状态
      • fulfilled: 操作成功
      • rejected: 操作失败

      如果一个 promise 已经被兑现(fulfilled)或被拒绝(rejected),那么我们也可以说它处于已敲定(settled)状态

    • PromiseResult (result)的初始值是 undefine
  • resovle和reject是JS自身提供的回调函数
    • 当 resovle(value) 被调用后, state: pending --> fulfilled,result: undefine --> value
    • 当 reject(error) 被调用或抛出异常后, state: pending --> rejected, result: undefine --> error

注意: 如果 value 是一个Promise对象的话 , 会直接返回该Promise对象

代码如下:

let promise = new Promise((resovle, reject) => {
  resovle(value); //state: pending --> fulfilled,result: undefine --> value
  reject(error)); //state: pending --> rejected, result: undefine --> error
  throw new Error("error"); //state: pending --> rejected, result: undefine --> new Error("error")
});

then,catch,finally 方法

当Promise对象处于 settled (fulfille或rejected)状态时,这三个方法可以对Promise进行进一步的操作。

then(handleFulfilled, handleRejected)

then是最重要的一个方法,catch和finally可以看做是它的变形。语法如下:

promise.then(
  (value) => {},//如果state:fulfilled, 执行第一个回调
  (error) => {}//如果state:rejected, 执行第二个回调
);
//回调函数的参数(value或error)的值为Promise的result属性的值

当我们只关心fulfilled状态的话(一般的用法,通常会用catch来捕捉error),我们可以只传入一个回调,像这样:

promise.then(
  (value) => {},//如果state:fulfilled, 执行回调
);
catch(handleRejected)

语法如下:

promise.catch(
  (error) => {}//如果state:rejected, 执行回调
);
//error的值为Promise的result属性的值

可以看出来catch其实和then差不多,但是它只能在rejected状态下执行

finally(handleRejected)

语法如下:

promise.finally(
  () => {}//如果state:fulfilled或state:rejected, 执行回调
);
//回调不需要参数,只要Promise对象处于settle状态就可以执行
//finally 不能获取Promise对象的result属性

Promise 链

三个方法都是异步操作的并且会默认返回一个Promise对象

那返回的Promise对象是怎样的呢?看代码和注释

let promise = new Promise((resolve, reject)=>{
    resolve(1);
})
// 一、回调函数抛出异常 --> state: rejected,result: new Error("error")
// 二、回调函数不抛出抛出异常
//      1.回调函数无返回值 --> state: fullfilled,result: undefine
//      1.回调函数有返回值(value) --> state: fullfilled,result: value
// 注意:如果返回值是Promise对象,会直接返回该Promise对象
let promise1 = promise.then(
  (value) => {
      throw new Error("error"); // state: rejected,result: new Error("error")
      return 1; // state: fullfilled,result: 1
  },
  (error) => {}
);

catch的返回值和then是一样的
catch就是一个没有第一个回调函数的then

posted @ 2022-03-13 22:18  GOD007  阅读(128)  评论(0)    收藏  举报