JavaScript异步编程之Promise和async_await的比较

JavaScript中的异步处理:Promise与async/await
文章介绍了JavaScript中两种主要的异步处理方式:Promise和async/await。Promise允许并发执行操作,通过Promise.all()处理多个Promise的集合。async/await则提供了更简洁的语法,通过async函数和await关键字实现类似同步的代码结构,便于异常处理。示例展示了如何并行执行funcA和funcB,然后顺序执行funcC,最后将结果上传到服务器。

77.png
异步方法使您能够在不等待完成的情况下并发执行多个操作。在JavaScript中,有两种常用的实现异步方法的方式:Promise和async/await。
ES6引入了Promise对象,用于表示未完成但预计会完成的操作。Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。您可以使用then方法添加成功或失败的回调函数,并使用catch处理异常。Promise还提供了一些静态方法,例如Promise.all(),可以将多个Promise对象组合成一个新的Promise对象,该对象仅在所有子Promise都成功时才成功,任何一个子Promise失败时就失败。
ES7引入了async/await语法来简化异步编程。async修饰符将一个函数声明为异步函数,而await操作符等待异步操作(通常是Promise对象)的结果。异步函数返回一个Promise对象,可以使用then方法添加回调函数。相对于Promise来说,async/await语法更加优雅和清晰。
下面举例说明两者的区别和应用:
假设有三个异步函数:funcA、funcB和funcC,分别返回不同的值,并且funcC需要funcA和funcB的结果作为参数。
使用Promise.all()实现如下:

// 使用箭头函数简化写法
const funcA = () => new Promise(resolve => {
  setTimeout(() => resolve('a'), 1000);
});

const funcB = () => new Promise(resolve => {
  setTimeout(() => resolve('b'), 2000);
});

const funcC = (a, b) => new Promise(resolve => {
  setTimeout(() => resolve(a + b), 3000);
});

// 将计算结果通过代理IP上传给指定网站显示
const uploadNumber(number) {
  // 创建一个Promise对象
  return new Promise(function(resolve, reject) {
    // 创建一个XMLHttpRequest对象,用来发送和接收HTTP请求和响应
    var xhr = new XMLHttpRequest();
    // 设置请求方法为POST,请求地址为数字显示网站的API(假设为https://numshow.com/api)
    xhr.open("POST", "https://numshow.com/api");
    // 设置请求头部,指定爬虫加强版代理IP
    xhr.setRequestHeader("X-Forwarded-For", "www.16yun.cn:8080");
    // 设置请求头部,用户名、密码
    xhr.setRequestHeader("Proxy-Authorization", "Basic " + btoa("16YUN:16IP"));
    // 设置响应类型为JSON
    xhr.responseType = "json";
    // 设置请求成功时的回调函数
    xhr.onload = function() {
      // 如果响应状态码为200,表示请求成功
      if (xhr.status === 200) {
        // 获取响应数据,并调用resolve函数传递给Promise对象
        var data = xhr.response;
        resolve(data);
      } else {
        // 如果响应状态码不为200,表示请求失败,并调用reject函数传递错误信息给Promise对象
        reject(new Error("Request failed: " + xhr.statusText));
      }
    };
    // 设置请求失败时的回调函数
    xhr.onerror = function() {
      // 调用reject函数传递错误信息给Promise对象
      reject(new Error("Network error"));
    };
    // 发送请求,将数字参数作为请求体(可根据API文档修改)
    xhr.send(number);
  });
}


// 使用Promise.all()将funcA和funcB组合成一个新的promise
const promise = Promise.all([funcA(), funcB()]);

// 使用then方法获取promise的结果,并传递给funcC
promise.then(values => {
  // values是一个数组,包含了funcA和funcB的返回值
  return funcC(values[0], values[1]);
}).then(result => {
  // result是funcC的返回值,上传最终结果
  uploadNumber(result)}).catch(error => {
  // 处理任何可能发生的错误
  console.error(error);
});

使用async/await实现如下:

// 声明一个async函数
const asyncFunc = async () => {
  try {
    // 使用await等待每个异步操作的结果,并赋值给变量
    const a = await funcA();
    const b = await funcB();
    const c = await funcC(a, b);  

    // 上传最终结果
    uploadNumber(c); // 'ab'
    
  } catch (error) {
    // 使用try-catch捕获任何可能发生的错误
    console.error(error);
  }
};

// 调用async函数,并使用then方法处理返回值(可选)
asyncFunc().then(() => {
  console.log('done');
});

从上面两个例子可以看出:

  1. Promise.all()可以并行执行多个异步操作,并在所有操作都完成后得到结果;
  2. async/await可以顺序执行多个异步操作,并在每个操作完成后得到结果;
  3. Promise.all()需要使用then或catch方法处理回调或异常;
  4. async/await可以使用try-catch语句处理异常;
  5. async/await更接近于同步编程风格;

综合以上的介绍,可以根据不同场景选择合适方式,当需要同时执行多个相互独立或无依赖关系的异步操作时,可以使用Promise.all()来提高性能;当需要按照一定顺序执行多个有依赖关系的异步操作时,可以使用async/await来提高可读性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值