首页 > 编程语言 >JavaScript 异步编程

JavaScript 异步编程

时间:2024-07-19 11:18:20浏览次数:10  
标签:异步 resolve err res JavaScript Promise result reject 编程

0x01 概念说明与基本使用

  • Promise 是在 ES6 中引入的类,用于更好地编写复杂的异步任务

    • 在 ES6 之前的异步请求的处理方案中,通常通过传递回调函数的方式处理请求结果,由于各个请求对回调函数不统一,每次请求时都需要查看相应的源码,造成效率低下,因此需要约定共同的标准,即 Promise 类
  • 在通过 new 创建 Promise 对象时,需要传入一个回调函数(称为 executor)

    const newPromise = new Promise(
      (resolve, reject) => {}
    );
    

    这个回调函数会立即执行,并传入另外两个回调函数:

    1. resolve:执行 Promise 对象的 then 方法传入的回调函数
    2. reject:执行 Promise 对象的 catch 方法传入的回调函数

    举例:异步请求处理(使用计时器模拟网络请求)

    function requestData(url) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if (url === "SRIGT") {
            resolve({
              data: ["SRIGT", "https://www.cnblogs.com/SRIGT"],
            });
          } else {
            reject({
              msg: "Invalid URL " + url,
            });
          }
        }, 1000);
      });
    }
    
    requestData("SR1GT").then(
      (res) => {
        console.log(res.data);
      },
      (err) => {
        console.log(err.msg);
      }
    );
    
  • Promise 在使用时,可被划分为三种状态:

    1. pending:待定中,即执行 executor()
    2. fulfilled / resolved:已决议,即执行 resolve()
    3. rejected:已拒绝,即执行 reject()
    new Promise((resolve, reject) => {
      // pending
    }).then(
      (res) => {
        // fulfilled  / resolved
      },
      (err) => {
        // rejected
      }
    );
    

    Promise 的状态一经确定则无法更改

  • resolve 方法参数包括:

    • 普通参数,如数字、字符串、数组、一般对象等

    • Promise 对象,则当前 Promise 对象的状态由传入的 Promise 对象决定

      new Promise((resolve, reject) => {
        resolve(
          new Promise((resolve, reject) => {
            reject("Error Message");
          })
        );
      }).then(
        (res) => {
          console.log("res:", res);
        },
        (err) => {
          console.log("err:", err);		// err: Error Message
        }
      );
      
    • 具有 then 方法的对象,则当前 Promise 对象的状态由传入的对象的 then 方法决定

      new Promise((resolve, reject) => {
        resolve({
          then: (resolve, reject) => {
            reject("Error Message");
          },
        });
      }).then(
        (res) => {
          console.log("res:", res);
        },
        (err) => {
          console.log("err:", err);		// err: Error Message
        }
      );
      

0x02 对象方法

  • 查看 Promise 的所有对象方法

    console.log(Object.getOwnPropertyDescriptors(Promise.prototype));
    
    方法 可写性 可枚举性 可配置性
    constructor [Function: Promise] true false true
    then [Function: then] true false true
    catch [Function: catch] true false true
    finally [Function: finally] true false true
    [Symbol(Symbol.toStringTag)] 'Promise' false false true

(1)then 方法

  • then 方法是 Promise 对上的方法,其在 Promise 的原型为 Promise.prototype.then

    • 接受两个参数,分别用于到达 fulfilled 或 rejected 状态时使用的回调函数
  • 同一个 Promise 对象可以被多次调用 then 方法

    • 当 Promise 中的 resolve 方法被调用时,所有 then 方法传入的回调函数都会执行
    const promise = new Promise((resolve, reject) => {
      resolve("Resolved");
    });
    
    promise.then((res) => console.log("res1:", res));
    promise.then((res) => console.log("res2:", res));
    promise.then((res) => console.log("res3:", res));
    
  • then 方法可以有返回值,是一个 Promise 对象,从而实现 Promise 的链式调用

    const promise = new Promise((resolve, reject) => {
      resolve("SRIGT");
    });
    
    promise
      .then((res) => {
        console.log(res);		// SRIGT
        return "srigt";
      })
      .then((res) => {
        console.log(res);		// srigt
      });
    

    此时,then 方法的 return 实际上遵循了 0x01 章关于 resolve 参数说明的内容

(2)catch 方法

  • executor 抛出异常时,会调用错误处理的回调函数,此时,catch 方法用于传入处理错误的回调函数

    const promise = new Promise((resolve, reject) => {
      reject("Error Message");
    });
    
    promise.catch((err) => console.log(err));
    
  • catch 方法支持链式调用

    • 从外向内捕获错误并执行

      const promise = new Promise((resolve, reject) => {
        resolve("Success");
      });
      
      promise
        .then((res) => {
          console.log(res);							// Success
          return new Promise((resolve, reject) => {
            reject("Error 2");
          });
        })
        .catch((err) => console.log("err1:", err))	// Error 2
        .catch((err) => console.log("err2:", err));	// [此语句未执行]
      
    • then 方法在 catch 方法后也可以执行

      const promise = new Promise((resolve, reject) => {
        reject("Error");
      });
      
      promise
        .catch((err) => console.log("err1:", err))	// err1: Error
        .catch((err) => console.log("err2:", err))
        .then((res) => console.log("res:", res));		// res: undefined
      
  • catch 方法支持多次调用

  • catch 方法可以 return,返回的值是一个 Promise 对象

    const promise = new Promise((resolve, reject) => {
      reject("Error");
    });
    
    promise
      .then((res) => console.log("res1", res))
      .catch((err) => {
        console.log("err", err);					// err: Error
        return "Success";
      })
      .then((res) => console.log("res2", res));		// res2: Success
    

(3)finally 方法

  • finally 方法是 ES9 新加入的特性,无论 fulfilled 还是 rejected 状态都会执行的方法

    const promise1 = new Promise((resolve, reject) => {
      resolve("Success");
    });
    const promise2 = new Promise((resolve, reject) => {
      reject("Error");
    });
    
    promise1.finally(() => console.log("Finally1"));
    promise2.finally(() => console.log("Finally2"));
    

Promises/A+ 规范:https://promisesaplus.com/

0x03 类方法

(1)resolve 与 reject

  • resolve

    const promise = Promise.resolve("Success");
    // 相当于
    const promise = new Promise((resolve, reject) => {
      resolve("Success");
    })
    
  • reject 使用与 resolve 类似

(2)all 与 allSettled

  • all 方法将多个 Promise 包裹为一个新的 Promise

    • 等待队列(数组参数)中所有 Promise 均处于 fulfilled 状态时执行 then 方法

      const promise1 = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve("Success1");
        }, 1000);
      });
      const promise2 = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve("Success2");
        }, 2000);
      });
      const promise3 = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve("Success3");
        }, 3000);
      });
      
      Promise.all([promise1, promise2, promise3, "All Over"]).then((res) =>
        console.log(res)		// [等待 3 秒后输出] [ 'Success1', 'Success2', 'Success3', 'All Over' ]
      );
      
    • 当队列中某个 Promise 处于 rejected 状态时,会中断执行并直接进入 catch 方法

      const promise1 = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve("Success1");
        }, 1000);
      });
      const promise2 = new Promise((resolve, reject) => {
        setTimeout(() => {
          reject("Error");
        }, 2000);
      });
      const promise3 = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve("Success3");
        }, 3000);
      });
      
      Promise.all([promise1, promise2, promise3, "All Over"])
        .then((res) => console.log(res))
        .catch((err) => console.log(err));		// [等待 2 秒后输出] Error
      
  • allSettled 方法在 ES11 中加入,不会因为某个 Promise 为 rejected 状态而中断,且最终状态一定为 fulfilled

    const promise1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("Success1");
      }, 1000);
    });
    const promise2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        reject("Error");
      }, 2000);
    });
    const promise3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("Success3");
      }, 3000);
    });
    
    Promise.allSettled([promise1, promise2, promise3, "All Over"])
      .then((res) => console.log(res));
    
    /*
     * [
     *   { status: 'fulfilled', value: 'Success1' },
     *   { status: 'rejected', reason: 'Error' },
     *   { status: 'fulfilled', value: 'Success3' },
     *   { status: 'fulfilled', value: 'All Over' }
     * ]
     */
    

(3)race 与 any

  • race 方法特点是:只要有一个 Promise 不是 pending 状态,则中断执行

    const promise1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        reject("Error1");
      }, 1000);
    });
    const promise2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        reject("Error2");
      }, 2000);
    });
    
    Promise.race([promise1, promise2])
      .then((res) => console.log(res))
      .catch((err) => console.log(err));	// [等待 1 秒后执行] Error
    
  • any 方法在 ES12 中加入,只要有一个 Promise 是 fulfilled 状态,则中断执行

    const promise1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        reject("Error1");
      }, 1000);
    });
    const promise2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        reject("Error2");
      }, 2000);
    });
    const promise3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("Success");
      }, 3000);
    });
    
    Promise.any([promise1, promise2, promise3])
      .then((res) => console.log(res))		// [等待 3 秒后执行] Success
      .catch((err) => console.log(err));
    
    • 如果所有 Promise 都是 rejected 状态,则等到所有 Promise 执行结束

      const promise1 = new Promise((resolve, reject) => {
        setTimeout(() => {
          reject("Error1");
        }, 1000);
      });
      const promise2 = new Promise((resolve, reject) => {
        setTimeout(() => {
          reject("Error2");
        }, 2000);
      });
      const promise3 = new Promise((resolve, reject) => {
        setTimeout(() => {
          reject("Error3");
        }, 3000);
      });
      
      Promise.any([promise1, promise2, promise3])
        .then((res) => console.log(res))
        .catch((err) => console.log(err.errors));		// [等待 3 秒后执行] [ 'Error1', 'Error2', 'Error3' ]
      

0x04 MyPromise

  1. 初步构建 MyPromise,通过 status 保存状态、result 保存结果、_this 保存 MyPromise,配置原型方法 then 并测试

    function MyPromise(executor) {
      this.status = "pending";
      this.result = undefined;
      const _this = this;
      function resolve(res) {
        if (_this.status !== "pending") return;
        _this.status = "fulfilled";
        _this.result = res;
      }
      function reject(res) {
        if (_this.status !== "pending") return;
        _this.status = "rejected";
        _this.result = res;
      }
      executor(resolve, reject);
    }
    
    MyPromise.prototype.then = function (successCallback, failureCallback) {   
      if (!successCallback) successCallback = value => value;
      if (!failureCallback) failureCallback = error => error;
    
      if (this.status === "fulfilled") {
        successCallback(this.result);
      } else if (this.status === "rejected") {
        failureCallback(this.result);
      }
    };
    

    测试

    const promise = new MyPromise((resolve, reject) => {
      resolve("Success");
      reject("Error");
    }).then(
      (res) => console.log(res),
      (err) => console.log(err)
    );
    
  2. 当在 pending 状态下执行时间较长,则需要收集回调,等待完成后再执行回调;为防止多次调用 Promise 的 then 方法造成后者覆盖前者,采用数组保存回调的收集

    function MyPromise(executor) {
      this.status = "pending";
      this.result = undefined;
      this.stack = [];
      const _this = this;
      function resolve(res) {
        if (_this.status !== "pending") return;
        _this.status = "fulfilled";
        _this.result = res;
        _this.stack.forEach((item) => item.successCallback(res));
      }
      function reject(res) {
        if (_this.status !== "pending") return;
        _this.status = "rejected";
        _this.result = res;
        _this.stack.forEach((item) => item.failureCallback(res));
      }
      executor(resolve, reject);
    }
    
    MyPromise.prototype.then = function (successCallback, failureCallback) {
      if (!successCallback) successCallback = value => value;
      if (!failureCallback) failureCallback = error => error;
    
      if (this.status === "fulfilled") {
        successCallback(this.result);
      } else if (this.status === "rejected") {
        failureCallback(this.result);
      } else {
        this.stack.push({
          successCallback,
          failureCallback,
        });
      }
    };
    

    测试

    const promise1 = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        resolve("Success2");
      }, 1000);
    }).then(
      (res) => console.log(res),
      (err) => console.log(err)
    );
    const promise2 = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        resolve("Success2");
      }, 1000);
    }).then(
      (res) => console.log(res),
      (err) => console.log(err)
    );
    
  3. 实现链式调用

    function MyPromise(executor) {
      this.status = "pending";
      this.result = undefined;
      this.stack = [];
      const _this = this;
      function resolve(res) {
        if (_this.status !== "pending") return;
        _this.status = "fulfilled";
        _this.result = res;
        _this.stack.forEach((item) => item.successCallback(res));
      }
      function reject(res) {
        if (_this.status !== "pending") return;
        _this.status = "rejected";
        _this.result = res;
        _this.stack.forEach((item) => item.failureCallback(res));
      }
      executor(resolve, reject);
    }
    
    MyPromise.prototype.then = function (successCallback, failureCallback) {
      if (!successCallback) successCallback = value => value;
      if (!failureCallback) failureCallback = error => error;
    
      return new MyPromise((resolve, reject) => {
        if (this.status === "fulfilled") {
          const result = successCallback(this.result);
          if (result instanceof MyPromise) {
            result.then(
              (res) => resolve(res),
              (err) => reject(err)
            );
          } else {
            resolve(result);
          }
        } else if (this.status === "rejected") {
          const result = failureCallback(this.result);
          if (result instanceof MyPromise) {
            result.then(
              (res) => resolve(res),
              (err) => reject(err)
            );
          } else {
            reject(result);
          }
        } else {
          this.stack.push({
            successCallback: () => {
              const result = successCallback(this.result);
              if (result instanceof MyPromise) {
                result.then(
                  (res) => resolve(res),
                  (err) => reject(err)
                );
              } else {
                resolve(result);
              }
            },
            failureCallback: () => {
              const result = failureCallback(this.result);
              if (result instanceof MyPromise) {
                result.then(
                  (res) => resolve(res),
                  (err) => reject(err)
                );
              } else {
                reject(result);
              }
            },
          });
        }
      });
    };
    

    测试

    const promise = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        resolve("Success1");
      }, 1000);
    })
      .then(
        (res) => {
          console.log("res1:", res);
          return new MyPromise((resolve, reject) => {
            setTimeout(() => {
              reject("Error2");
            }, 1000);
          });
        },
        (err) => console.log("err1:", err)
      )
      .then(
        (res) => console.log("res2:", res),
        (err) => console.log("err2:", err)
      );
    
  4. 实现 catch 方法

    MyPromise.prototype.catch = function (failureCallback) {
      this.then(undefined, failureCallback);
    };
    
  5. 完整自制的 MyPromise

    function MyPromise(executor) {
      this.status = "pending";
      this.result = undefined;
      this.stack = [];
      const _this = this;
      function resolve(res) {
        if (_this.status !== "pending") return;
        _this.status = "fulfilled";
        _this.result = res;
        _this.stack.forEach((item) => item.successCallback(res));
      }
      function reject(res) {
        if (_this.status !== "pending") return;
        _this.status = "rejected";
        _this.result = res;
        _this.stack.forEach((item) => item.failureCallback(res));
      }
      executor(resolve, reject);
    }
    
    MyPromise.prototype.then = function (successCallback, failureCallback) {
      if (!successCallback) successCallback = () => {};
      if (!failureCallback) failureCallback = () => {};
    
      return new MyPromise((resolve, reject) => {
        if (this.status === "fulfilled") {
          const result = successCallback(this.result);
          if (result instanceof MyPromise) {
            result.then(
              (res) => resolve(res),
              (err) => reject(err)
            );
          } else {
            resolve(result);
          }
        } else if (this.status === "rejected") {
          const result = failureCallback(this.result);
          if (result instanceof MyPromise) {
            result.then(
              (res) => resolve(res),
              (err) => reject(err)
            );
          } else {
            reject(result);
          }
        } else {
          this.stack.push({
            successCallback: () => {
              const result = successCallback(this.result);
              if (result instanceof MyPromise) {
                result.then(
                  (res) => resolve(res),
                  (err) => reject(err)
                );
              } else {
                resolve(result);
              }
            },
            failureCallback: () => {
              const result = failureCallback(this.result);
              if (result instanceof MyPromise) {
                result.then(
                  (res) => resolve(res),
                  (err) => reject(err)
                );
              } else {
                reject(result);
              }
            },
          });
        }
      });
    };
    
    MyPromise.prototype.catch = function (failureCallback) {
      this.then(undefined, failureCallback);
    };
    

0x05 async 与 await

  • asyncawait 在 ES7 中加入,使异步代码看起来和写起来更像是同步代码

  • async 返回 Promise 对象,而 await 接收 Promise 对象并返回该对象的结果(如果不是 Promise 对象则返回对应的值)

    async function requestData() {
      const result = await new Promise((resolve, reject) => {
        resolve("Success");
      });
      return result;
    }
    const result = requestData();
    console.log(result);
    result.then(
      (res) => console.log(res),
      (err) => console.log(err)
    );
    

-End-

标签:异步,resolve,err,res,JavaScript,Promise,result,reject,编程
From: https://www.cnblogs.com/SRIGT/p/18311128

相关文章

  • GESP编程能力等级认证C++编程真题解析 | 2024年3月五级
    学习C++从娃娃抓起!记录下CCF-GESP备考学习过程中的题目,记录每一个瞬间。附上汇总贴:GESP编程能力等级认证C++编程真题解析|汇总单选题第1题唯一分解定理描述的内容是()?A.任意整数都可以分解为素数的乘积B.每个合数都可以唯一分解为一系列素数的乘积C.两个不同的......
  • 【Linux网络编程-7】epoll边沿触发
    非阻塞recvEAGAIN、EWOULDBLOCK错误码值11返回值含义>0接收字节数0接收FIN包,连接被对端断开-1(errno==EAGAIN||EWOULDBLOCK)表示还有数据未读。反之,则表示发生了错误。//epollServer.cpp#include<stdio.h>#include<stdlib.h>#include<string.h>#in......
  • 初写博客之自己的编程之路正式开启
    初写博客之自己的编程之路正式开启前言:本篇文章是第一次在CSDN上面写博客文章,为了让大家也能在我学习在编程的道路学习道路上获得一些属于自己的灵感。本篇文章将从以下方面铺展开来:①关于本人的自我介绍②以后自己在编程上的目标③自己将如何学习编程④自己每周花在编......
  • Shell编程速查手册(仅入门)
    一.Shell概述Shell是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言。Shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。Shell脚本(shellscript),是一种为shell编写的脚本程序......
  • 大学生HTML期末大作业——HTML+CSS+JavaScript美食网站(西餐)
    HTML+CSS+JS【美食网站】网页设计期末课程大作业web前端开发技术web课程设计网页规划与设计......
  • Leetcoede编程基础0到1——1768. 交替合并字符串& 389. 找不同
    1768.交替合并字符串题目描述:给你两个字符串 word1 和 word2 。请你从 word1 开始,通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长,就将多出来的字母追加到合并后字符串的末尾。返回 合并后的字符串 。输入输出实例:  示例1:输入:word1="ab......
  • 深入探讨:使用 Spring AOP 实现 Lock4j 的声明式和编程式分布式锁
    深入探讨:使用SpringAOP实现Lock4j的声明式和编程式分布式锁在现代分布式系统中,分布式锁是一个非常重要的概念。它可以帮助我们在多个节点之间协调资源访问,防止数据不一致和竞争条件。今天,我们将深入探讨如何使用Lock4j和SpringAOP来实现声明式和编程式的分布式锁。什......
  • 深入探讨 Spring 6 的面向切面编程(AOP)
    深入探讨Spring6的面向切面编程(AOP)大家好,今天我们来聊聊Spring6中的面向切面编程(AOP)。AOP是Spring框架中一个非常强大的特性,它可以帮助我们在不改变原有代码的情况下,添加一些通用的功能,比如日志记录、事务管理、安全检查等。什么是AOP?AOP,全称Aspect-OrientedProgra......
  • 高质量C/C++编程指南总结(十)—— const 用法
    const的用法1)用const修饰函数的输入参数如果输入的参数采用“指针传递”,那么加const修饰可以防止意外地改动该指针,起到保护作用。如果输入参数采用“值传递”,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加const修饰。对于非内部数据类......
  • async sqlalchemy 异步查询
      实体和属性返回多条数据 fetchall()q=select(models.User)result=awaitsession.execute(q)foriinresult:print(i)fetchone()返回一条数据q=select(models.User)result=awaitsession.execute(q)print(result.fetchone())>>>(<model.models.U......