promise看这一篇就够了

简介: promise看这一篇就够了

前言



本片文章博主主要从介绍promise->用法->手写实现->常用API->特性->适用场景六个方面给大家展开讲解

感兴趣的不妨看下去吧 记得三联支持作者


介绍



Promise是JavaScript中用于处理异步操作的一种机制。它解决了传统回调函数嵌套(callback hell)带来的可读性差、错误处理困难等问题,使得异步代码更加清晰、可维护。


一个Promise代表了一个异步操作的最终完成或失败,并且可以返回一个值。它有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。一旦Promise的状态变为fulfilled或rejected,就称为“settled”(已定型)。


在以往我们如果处理多层异步操作,我们往往会像下面那样编写我们的代码

doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('得到最终结果: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);


阅读上面代码,是不是很难受,上述形成了经典的回调地狱

现在通过Promise的改写上面的代码

doSomething().then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('得到最终结果: ' + finalResult);
})
.catch(failureCallback);


瞬间感受到promise解决异步操作的优点:

  • 链式操作减低了编码难度
  • 代码可读性明显增强


下面我们正式来认识promise:

状态

promise对象仅有三种状态

  • pending(进行中)
  • fulfilled(已成功)
  • rejected(已失败)
    特点
  • 对象的状态不受外界影响,只有异步操作的结果,可以决定当前是哪一种状态
  • 一旦状态改变(从pending变为fulfilled和从pending变为rejected),就不会再变,任何时候都可以得到这个结果

流程

认真阅读下图,我们能够轻松了解promise整个流程

f78bc16e13464ccaa17351023e7406a5.png


用法



Promise对象是一个构造函数,用来生成Promise实例

const promise = new Promise(function(resolve, reject) {});


Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject

  • resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”
  • reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”


手写实现一个promise



class MyPromise {
  constructor(executor) {
    this.status = 'pending'; // Promise的状态,初始为pending
    this.value = undefined; // Promise的值,默认为undefined
    this.callbacks = []; // 存储then回调函数的数组
    const resolve = (value) => {
      if (this.status === 'pending') {
        this.status = 'fulfilled'; // 改变Promise的状态为fulfilled
        this.value = value; // 设置Promise的值
        // 依次执行then回调函数
        this.callbacks.forEach((callback) => {
          callback.onFulfilled(value);
        });
      }
    };
    const reject = (reason) => {
      if (this.status === 'pending') {
        this.status = 'rejected'; // 改变Promise的状态为rejected
        this.value = reason; // 设置Promise的值
        // 依次执行then回调函数
        this.callbacks.forEach((callback) => {
          callback.onRejected(reason);
        });
      }
    };
    try {
      executor(resolve, reject); // 执行executor函数,并传入resolve和reject作为参数
    } catch (error) {
      reject(error); // 如果executor执行出错,则将错误信息传递给reject
    }
  }
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      const handleCallback = (callback) => {
        try {
          const result = callback(this.value); // 执行回调函数,并传入Promise的值
          if (result instanceof MyPromise) {
            result.then(resolve, reject); // 如果回调函数返回的是一个Promise,使用then继续处理
          } else {
            resolve(result); // 否则将回调函数的返回值作为新Promise的值
          }
        } catch (error) {
          reject(error); // 如果回调函数执行出错,则将错误信息传递给reject
        }
      };
      if (this.status === 'pending') {
        this.callbacks.push({
          onFulfilled: (value) => handleCallback(onFulfilled),
          onRejected: (reason) => handleCallback(onRejected)
        });
      } else if (this.status === 'fulfilled') {
        handleCallback(onFulfilled);
      } else if (this.status === 'rejected') {
        handleCallback(onRejected);
      }
    });
  }
  catch(onRejected) {
    return this.then(null, onRejected); // catch方法实际上是then方法的语法糖,只接受onRejected回调
  }
  static resolve(value) {
    return new MyPromise((resolve) => resolve(value)); // 创建一个状态为fulfilled的Promise,并将指定的值传递给resolve
  }
  static reject(reason) {
    return new MyPromise((resolve, reject) => reject(reason)); // 创建一个状态为rejected的Promise,并将指定的原因传递给reject
  }
  static all(promises) {
    return new MyPromise((resolve, reject) => {
      const results = []; // 存储每个Promise的结果
      let count = 0; // 记录已完成的Promise数量
      promises.forEach((promise, index) => {
        promise.then((value) => {
          results[index] = value;
          count++;
          if (count === promises.length) {
            resolve(results); // 所有Promise都完成时,将结果传递给resolve
          }
        }, reject);
      });
    });
  }
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach((promise) => {
        promise.then(resolve, reject); // 只要有一个Promise完成或拒绝,就将结果传递给resolve或reject
      });
    });
  }
}


常用API



  • then(onFulfilled, onRejected):then方法用于注册回调函数,在Promise状态发生改变时执行相应的回调函数。onFulfilled用于处理Promise状态变为fulfilled时的情况,onRejected用于处理Promise状态变为rejected时的情况。then方法返回一个新的Promise。
  • catch(onRejected):catch方法是then方法的语法糖,只接受onRejected回调函数,用于处理Promise状态变为rejected时的情况。catch方法返回一个新的Promise。
  • Promise.resolve(value):静态方法resolve用于创建一个状态为fulfilled的Promise,并将指定的值传递给resolve。
  • Promise.reject(reason):静态方法reject用于创建一个状态为rejected的Promise,并将指定的原因传递给reject。
  • Promise.all(promises):静态方法all接收一个包含多个Promise的数组,返回一个新的Promise。当所有Promise都变为fulfilled时,新的Promise变为fulfilled,并将每个Promise的值按顺序传递给resolve;如果有任何一个Promise变为rejected,新的Promise将变为rejected,并将第一个被reject的Promise的原因传递给reject。
  • Promise.race(promises):静态方法race接收一个包含多个Promise的数组,返回一个新的Promise。只要有一个Promise变为fulfilled或rejected,新的Promise就会变为相应的状态,并将第一个完成的Promise的结果传递给resolve或reject。


特性



  • 异步操作管理:Promise是用于处理异步操作的一种机制。它可以将异步任务封装为一个Promise对象,使得异步任务的执行和结果可以更加可控和可预测。
  • 状态管理:Promise具有三种状态:pending(进行中)、fulfilled(已完成)和rejected(已拒绝)。初始状态为pending,当异步操作成功完成时状态变为fulfilled,若发生错误则状态变为rejected。状态一旦改变,就不可再变。
  • 链式调用:Promise通过then方法支持链式调用。then方法接收两个参数:onFulfilled(当Promise状态变为fulfilled时调用的回调函数)和onRejected(当Promise状态变为rejected时调用的回调函数)。每次调用then方法后都会返回一个新的Promise对象,因此可以连续调用多个then方法形成链式操作。
  • 值传递:Promise可以将值在异步操作之间传递。当一个Promise状态变为fulfilled时,可以将其值传递给下一个Promise或者通过回调函数返回给调用方。
  • 错误处理:Promise具有错误传递和捕获的能力。在Promise链中,任何一个Promise出现异常都会触发onRejected回调函数,并将异常信息传递到catch方法或后续的错误处理函数中。
  • 多个Promise的协同处理:Promise提供了静态方法如Promise.all和Promise.race,用于处理多个Promise的协同处理情况。Promise.all可以等待多个Promise都成功完成后再执行后续操作,而Promise.race会在第一个完成的Promise上触发后续操作。


适用场景



  • 异步操作:Promise可用于处理异步操作,使代码更易读、维护和扩展。通过then方法链式调用,可以按顺序执行一系列异步操作。
  • AJAX 请求:使用Promise可以更优雅地处理AJAX请求,通过将AJAX封装成Promise,可以在请求成功或失败后执行相应的回调函数。
  • 并发控制:Promise.all方法可以用于并发控制,当多个异步任务都完成时再进行下一步操作。
  • 错误处理:Promise的特性之一是错误捕获和传递。通过catch方法可以统一处理Promise链中的错误,提高代码的可读性和错误管理能力。


后言



创作不易 如果该文章对您有帮助 不妨三联支持一下作者 感谢

下一期会出 promise的链式调用和promise的嵌套的实现

如果感兴趣下次来看


目录
相关文章
|
4月前
|
前端开发 JavaScript API
【面试题】说说 Promise是什么?如何使用
【面试题】说说 Promise是什么?如何使用
|
6月前
|
前端开发
手写基础 promise
手写基础 promise
42 0
|
7月前
|
前端开发
Promise的用法&原理&手写实现-2
Promise的用法&原理&手写实现-2
21 1
|
9月前
|
前端开发
一篇搞懂promise
一篇搞懂promise
84 0
|
7月前
|
前端开发 JavaScript API
Promise的用法&原理&手写实现-1
Promise的用法&原理&手写实现-1
25 0
|
8月前
|
前端开发 JavaScript
搞懂Promise
搞懂Promise
28 0
|
9月前
|
前端开发 JavaScript API
谈谈你对promise的理解?
Promise是ES6异步编程的一种解决方案(目前最先进的解决方案是async和await的搭配(ES8),但是它们是基于promise的),从语法上讲,Promise是一个对象或者说是构造函数,用来封装异步操作并可以获取其成功或失败的结果。
|
10月前
|
前端开发
Promise是什么?怎么用?
Promise 是一种异步编程的解决方案。它可以使异步操作更加清晰、简单、优雅,避免了回调地狱的问题。Promise 对象表示一个异步操作的最终完成或失败,并且它的最终状态(完成或失败)和返回值(或错误)不依赖于调用它的代码。
|
11月前
|
前端开发 JavaScript
web前端面试高频考点——JavaScript 篇(二)【JS 异步进阶】Event Loop、then 和 catch、async/await、宏任务微任务、手撕 Promise 源码
web前端面试高频考点——JavaScript 篇(二)【JS 异步进阶】Event Loop、then 和 catch、async/await、宏任务微任务、手撕 Promise 源码
148 0
|
前端开发
前端学习案例21-promise详解3
前端学习案例21-promise详解3
45 0
前端学习案例21-promise详解3