Promise构造函数,属性以及方法应用

(一)promise构造函数

Promise构造函数,属性以及方法应用_第1张图片

 (二)将基于回调的 API 转换为基于 Promise 的 API

 function myAsyncFunction(url) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open('GET',url);
        xhr.onload=() => resolve(xhr.responseText);
        xhr.onerror=() => reject(xhr.statusText);
        xhr.send();
    })
  }

(三)Promise.all()

Promise.all() 静态方法接受一个 Promise 可迭代对象作为输入,并返回一个 Promise。当所有输入的 Promise 都被兑现时,返回的 Promise 也将被兑现(即使传入的是一个空的可迭代对象),并返回一个包含所有兑现值的数组。如果输入的任何 Promise 被拒绝,则返回的 Promise 将被拒绝,并带有第一个被拒绝的原因。

Promise构造函数,属性以及方法应用_第2张图片

  const promise1 = Promise.resolve(3);
  const promise2 = 42;
  const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'foo')
  });
  Promise.all([promise1,promise2,promise3]).then((value) => {
    console.log(value)
  })

Promise构造函数,属性以及方法应用_第3张图片

 状态为fulfilled 和rejected

(四)Promise.all 的异步性和同步性

Promise构造函数,属性以及方法应用_第4张图片

如果 Promise.all 失败,也是一样的:

Promise构造函数,属性以及方法应用_第5张图片 只有当传递给 Promise.all 的 iterable 为空时,Promise.all 才会同步解

Promise构造函数,属性以及方法应用_第6张图片

   const p = Promise.all([]);// 将会立即解决
   const p2 = Promise.all([1377, 'hi']);// 非promise值将被忽略,但求值是异步进行的
   console.log(p);
   console.log(p2);
   setTimeout(() => {
    console.log("队列现在为空");
    console.log(p2)
   })

 (五)将 Promise.all() 与异步函数一起使用

Promise构造函数,属性以及方法应用_第7张图片

 function promptForDishChoice() {
    return new Promise((resolve,reject) => {
        const dialog = document.createElement("dialog");
        dialog.innerHTML = `
        

What would you like to eat?

  • `; dialog.addEventListener("close",() => { if(dialog.returnValue === "ok") { resolve(dialog.querySelector("select").value) } else { reject(new Error("user canceled dialog")) } }); document.body.appendChild(dialog); dialog.showModal(); }) } async function fetchPrices() { const response = await promptForDishChoice(); console.log(response,'response') // return await response.json(); } fetchPrices()

    promise.all()

    async function getPrice () {
        const [choice, prices] = await Promise.all([
            promptForDishChoice(),
            fetchPrice(),
        ]);
        return prices[choice]
        }

    Promise.all 的快速失败行为
     

    Promise.all 在任意一个传入的 promise 失败时返回失败。例如,如果你传入四个超时后解决的 promise 和一个立即拒绝的 promise,那么 Promise.all 将立即被拒绝。

    Promise构造函数,属性以及方法应用_第8张图片
     

    const p1 = new Promise((resolve, reject) => {
            setTimeout(() => resolve("一"),1000);
        })
        const p2 = new Promise((resolve, reject) => {
            setTimeout(() => resolve("二"),2000);
        })
        const p3 = new Promise((resolve, reject) => {
            setTimeout(() => resolve("三"),3000);
        })
        const p4 = new Promise((resolve, reject) => {
            setTimeout(() => resolve("四"),4000);
        })
        const p5 = new Promise((resolve, reject) => {
           reject(new Error("拒绝"))
        })
    
        // 使用.catch
        Promise.all([p1,p2,p3,p4,p5])
            .then((values) => {
                console.log(values)
            })
            .catch((error) => {
                console.log(error.message)
            })

     通过处理可能的拒绝,可以更改此行为:

    Promise构造函数,属性以及方法应用_第9张图片

    (六) Promise.allSettled()

    Promise.allSettled() 静态方法将一个 Promise 可迭代对象作为输入,并返回一个单独的 Promise,当所有输入的 Promise都已敲定时(包括传入空的可迭代对象时),返回的 Promise 将被兑现,并带有描述每个 Promise结果的对象数组。

    Promise构造函数,属性以及方法应用_第10张图片

     const promise1 = Promise.resolve(3);
        const promise2 = new Promise((resolve, reject) => {
            setTimeout(reject, 100, 'foo')
        })
        const promises = [promise1, promise2];
        Promise.allSettled(promises).then((results) => {
            results.forEach((result) => {
                console.log(result.status)
            })
        })

     Promise构造函数,属性以及方法应用_第11张图片

    (七)Promise.any() 

    Promise.any() 静态方法将一个 Promise 可迭代对象作为输入,并返回一个 Promise。当输入的任何一个 Promise 兑现时,这个返回的 Promise 将会兑现,并返回第一个兑现的值。当所有输入 Promise 都被拒绝(包括传递了空的可迭代对象)时,它会以一个包含拒绝原因数组的 AggregateError 拒绝。

    Promise构造函数,属性以及方法应用_第12张图片

    Promise.any() 会以第一个兑现的 Promise 来兑现,即使有 Promise 先被拒绝。这与 Promise.race() 不同,后者会使用第一个敲定的 Promise 来兑现或拒绝。 

    Promise构造函数,属性以及方法应用_第13张图片

     如果没有 Promise 被兑现,Promise.any() 将使用 AggregateError 进行拒绝。

    Promise构造函数,属性以及方法应用_第14张图片

    在这个例子,我们有一个获取图片并返回 blob 的函数,我们使用 Promise.any() 来获取一些图片并显示第一张可用的图片(即最先解决的那个 promise)。

     async function fetchAndDecode(url, description) {
            const res = await fetch(url);
            if(!res.ok) {
                throw new Error(`HTTP错误!状态码:${res.status}`)
            }
            const data = await res.blob();
            return [data, description]
        }
      const coffee = fetchAndDecode("coffee.jpg","Coffee");
      const tea = fetchAndDecode('tea.jpg','Tea');
    
      Promise.any([coffee, tea])
      .then(([blob, description]) => {
        const objectURL = URL.createObjectURL(blob);
        const image = document.createElement("img");
        image.src = objectURL;
        image.alt = description;
        document.body.appendChild(image)
      })
      .catch((e) => {
        console.error(e)
      })

     (八)Promise.prototype.catch()

    Promise 实例的 catch() 方法用于注册一个在 promise 被拒绝时调用的函数。它会立即返回一个等效的 Promise 对象,这可以允许你链式调用其他 promise 的方法。此方法是 Promise.prototype.then(undefined, onRejected) 的一种简写形式。

    Promise构造函数,属性以及方法应用_第15张图片

    Promise构造函数,属性以及方法应用_第16张图片

    在链式调用中使用 catch() 方法

    Promise构造函数,属性以及方法应用_第17张图片

     在异步函数内部抛出的错误会像未捕获的错误一样:

    Promise构造函数,属性以及方法应用_第18张图片

     Promise构造函数,属性以及方法应用_第19张图片

     如果 Promise 已兑现,catch() 不会被调用

    Promise构造函数,属性以及方法应用_第20张图片

    (九)Promise.prototype.finally() 

    Promise 实例的 finally() 方法用于注册一个在 promise 敲定(兑现或拒绝)时调用的函数。它会立即返回一个等效的 Promise 对象,这可以允许你链式调用其他 promise 方法。

    这可以让你避免在 promise 的 then() 和 catch() 处理器中重复编写代码。

    Promise构造函数,属性以及方法应用_第21张图片

     Promise构造函数,属性以及方法应用_第22张图片

     使用 finally()

      let isLoading = true;
       fetch(myRequest)
       .then((response) => {
        const contentType = response.headers.get("content-type");
        if(contentType && contentType.includes("application/json")) {
            return response.json()
        }
        throw new TypeError('ERROR  ERROR')
       }).then((json) => {
    
       }).catch((error) => {
        console.error(error)
       }).finally(() => {
        isLoading = false
       })

    (十)Promise.race()

    Promise.race() 静态方法接受一个 promise 可迭代对象作为输入,并返回一个 Promise。这个返回的 promise 会随着第一个 promise 的敲定而敲定。

    Promise构造函数,属性以及方法应用_第23张图片

    使用 Promise.race()

    这个例子展示了如何使用 Promise.race() 来比较多个使用 setTimeout() 实现的计时器。计时时间最短的计时器总是赢得竞态,并成为返回的 promise 状态。

    Promise.race 的异步性

    以下示例演示了 Promise.race 的异步性。与其他 promise 并发方法不同,Promise.race 总是异步的:即使 iterable 为空,它也永远不会同步地完成。

    Promise构造函数,属性以及方法应用_第24张图片

     // 传入一个已经解决的Promise数组,以尽快触发Promise.race
      const resolvedPromiseArray = [Promise.resolve(33), Promise.resolve(44)];
      const p = Promise.race(resolvedPromiseArray);
      // 立即打印p的值
      console.log(p);
      // 使用setTimeout.我们可以在堆栈为空后执行代码
      setTimeout(() => {
        console.log("堆栈现在为空");
        console.log(p)
      })

    一个空的可迭代对象会导致返回的 Promise 一直处于待定状态:

    Promise构造函数,属性以及方法应用_第25张图片

    const foreverPendingPromise = Promise.race([]);
      console.log(foreverPendingPromise);
      setTimeout(() => {
        console.log("堆栈现在为空");
        console.log(foreverPendingPromise)
      })

    如果可迭代对象包含一个或多个非 Promise 值和/或一个已经敲定的 Promise,则 Promise.race 会以数组中找到的第一个这样的值敲定:

    Promise构造函数,属性以及方法应用_第26张图片

     const foreverPendingPromise = Promise.race([]);
      const alreadyFulfilledProm = Promise.resolve(100);
      const arr = [foreverPendingPromise,alreadyFulfilledProm,"非Promise值"];
      const arr2 = [foreverPendingPromise,'非Promise值',Promise.resolve(100)]
      const p = Promise.race(arr);
      const p2 = Promise.race(arr2);
      console.log(p);
      console.log(p2);
      setTimeout(() => {
        console.log("堆栈现在为空");
        console.log(p);
        console.log(p2);
      })

    使用 Promise.race() 实现请求超时

    你可以使用一个定时器来与一个可能持续很长时间的请求进行竞争,以便超出时间限制时,返回的 Promise 自动拒绝。

    const data = Promise.race([
        fetch('/api'),
        new Promise((resolve, reject) => {
            // 5秒后拒绝
            setTimeout(() => reject(new Error('请求超时')),5000)
        })
      ])
      .then((res) => res.json())
      .catch((err) => displayError(err))

    使用 Promise.race() 检测 Promise 的状态

    const p1 = new Promise((res) => setTimeout(() => res(100), 100));
        const p2 = new Promise((res) => setTimeout(() => res(200), 200));
        const p3 = new Promise((res, rej) => setTimeout(() => rej(300), 100));
    
        function promiseState(promise) {
        const pendingState = { status: "待定" };
            return Promise.race([promise, pendingState]).then(
                (value) => (value === pendingState ? value : { status: "已兑现", value }),
                (reason) => ({ status: "已拒绝", reason }),
            );
        }
        async function getStates() {
        console.log(await promiseState(p1));
        console.log(await promiseState(p2));
        console.log(await promiseState(p3));
        }
    
        console.log("开始状态:");
        getStates();
        setTimeout(() => {
        console.log("等待 100ms 后:");
        getStates();
        }, 100);

    与 Promise.any() 的比较

    Promise.race 方法以可迭代对象中第一个敲定的 Promise 作为敲定值。

    Promise构造函数,属性以及方法应用_第27张图片

    const promise1 = new Promise((resolve, reject) => {
      setTimeout(resolve, 500, "一");
    });
    
    const promise2 = new Promise((resolve, reject) => {
      setTimeout(reject, 100, "二");
    });
    
    Promise.race([promise1, promise2])
      .then((value) => {
        console.log("成功,值为:", value);
      })
      .catch((reason) => {
        // 只有 promise1 成功兑现,但 promise2 更快
        console.error("失败,原因为:", reason);
      });
    // 失败,原因为:二

    Promise.any 方法以可迭代对象中第一个被兑现的 Promise 作为兑现值。

    Promise构造函数,属性以及方法应用_第28张图片

      const promise1 = new Promise((resolve, reject) => {
      setTimeout(resolve, 500, "一");
    });
    
    const promise2 = new Promise((resolve, reject) => {
      setTimeout(reject, 100, "二");
    });
    
    Promise.any([promise1, promise2])
      .then((value) => {
        // 只有 promise1 成功兑现,即使 promise2 更快敲定
        console.log("成功,值为:", value);
      })
      .catch((reason) => {
        console.error("失败,原因为:", reason);
      });
    // 成功,值为:一

    Promise.reject()

    Promise.reject() 静态方法返回一个已拒绝(rejected)的 Promise 对象,拒绝原因为给定的参数。

    Promise构造函数,属性以及方法应用_第29张图片

    function resolved(result) {
            console.log('Resolved')
        }
        function rejected(result) {
            console.error(result)
        }
        Promise.reject(new Error('fail'))
        .then(resolved,rejected)

    Promise.reject 静态方法返回一个被拒绝的 Promise 对象。

    该函数可以用 resolve 和 reject 回调函数作为参数进行调用。Promise.reject() 实际上相当于 new Promise((resolve, reject) => reject(reason)) 的简写形式。

    使用 Promise.reject() 静态方法

    Promise构造函数,属性以及方法应用_第30张图片

     Promise.reject(new Error("失败"))
            .then(
                () => {
                    // 不会被调用
                },
                (error) => {
                    console.error(error)
                }
            )

    reject 一个 promise 对象

    与 Promise.resolve 不同,Promise.reject 方法不会重用已存在的 Promise 实例。它始终返回一个新的 Promise 实例,该实例封装了拒绝的原因(reason)。

    Promise构造函数,属性以及方法应用_第31张图片

    在非 Promise 构造函数上调用 reject()

    Promise构造函数,属性以及方法应用_第32张图片

    Promise.resolve()

    Promise构造函数,属性以及方法应用_第33张图片

    使用 Promise.resolve 静态方法

    Promise构造函数,属性以及方法应用_第34张图片

    Promise构造函数,属性以及方法应用_第35张图片

    resolve 另一个 promise

    Promise.resolve() 方法会重用已存在的 Promise 实例。如果它正在解决一个原生的 Promise,它将返回同一 Promise 实例,而不会创建一个封装对象。

    Promise构造函数,属性以及方法应用_第36张图片

    resolve thenable 对象并抛出错误

    嵌套的 thenable 对象将被“深度展平”为单个 Promise 对象

    const thenable = {
        then(onFulfilled,onRejected) {
            onFulfilled({
                // 该thenable对象将兑现为另外一个thenable对象
                then(onFulfilled,onRejected) {
                    onFulfilled(42)
                }
            })
        }
       }
       Promise.resolve(thenable).then((v) => {
        console.log(v);// 12
       })

    警告: 不要在一个解决为自身的 thenable 对象上调用 Promise.resolve()。这将导致无限递归,因为它试图展平一个无限嵌套的 Promise。

    const thenable = {
      then(onFulfilled, onRejected) {
        onFulfilled(thenable);
      },
    };
    
    Promise.resolve(thenable); // 将会导致无限递归。

    在非 Promise 构造函数上调用 resolve()

     class NotPromise {
        constructor(executor) {
            executor(
                (value) => console.log("已解决",value),
                (reason) => console.log("已拒绝",reason)
            )
        }
       }
       Promise.resolve.call(NotPromise, 'foo');// 输出 “已解决foo”
     const thenable = {
      then(onFulfilled, onRejected) {
        onFulfilled({
          // 该 thenable 对象将兑现为另一个 thenable 对象
          then(onFulfilled, onRejected) {
            onFulfilled(42);
          },
        });
      },
    };
    
    Promise.resolve.call(NotPromise, thenable); // 输出 "已兑现 { then: [Function: then] }"

    Promise.prototype.then()

    参数

    onFulfilled 可选

    一个在此 Promise 对象被兑现时异步执行的函数。它的返回值将成为 then() 返回的 Promise 对象的兑现值。此函数被调用时将传入以下参数:

    onRejected 可选

    一个在此 Promise 对象被拒绝时异步执行的函数。它的返回值将成为 catch() 返回的 Promise 对象的兑现值。此函数被调用时将传入以下参数:

    如果 onFulfilled 返回一个 Promise,那么 then 的返回值将根据该 Promise 的最终状态被兑现或被拒绝。

    你可以使用链式调用,在一个函数上实现基于 Promise 的 API,在另一个函数之上。

    参考原文:(以上都是来自官方文档,此文档仅供学习参考笔记记录)

    Promise() 构造函数 - JavaScript | MDN (mozilla.org)

    你可能感兴趣的:(javascript,前端,开发语言)