js中async/await与Promise的区别

 更新时间:2024年04月09日 09:59:59   作者:接着奏乐接着舞。  
在JavaScript开发中,异步编程是一个无法避免的话题,本文主要介绍了js中async/await与Promise的区别,具有一定的参考价值,感兴趣的可以了解一下

基本概念

首先,我们需要明白async/await和Promise都是JavaScript中处理异步操作的API。

  • Promise: 是一种代表了某个异步操作最终完成(或失败)及其结果值的对象。
  • async/await: 是基于Promise的语法糖,它允许我们以更同步的方式编写异步代码。

使用Promise

基本语法
Promise.all() 接受一个 Promise 数组作为参数,返回一个新的 Promise 实例。这个新 Promise 的行为表现为:

  • 当所有传入的 Promises 都成功解决时,它会解决(resolve)为一个包含所有 Promises 结果的数组。
  • 如果任何一个 Promise 失败(即被拒绝),Promise.all() 返回的 Promise 会立即失败,并返回相应的错误。

在没有async/await之前,我们通常通过链式调用.then().catch()方法来处理Promise。例如,如果要按顺序执行两个异步操作,可能会这样写:

doSomethingAsync()
  .then(result => {
    console.log(result);
    return doSomethingElseAsync(result);
  })
  .then(newResult => {
    console.log(newResult);
  })
  .catch(error => {
    console.error('Something went wrong', error);
  });

这种方式可以有效地处理异步操作,但当涉及到多个异步操作时,代码可能会变得复杂和难以阅读,这通常被称为“回调地狱”。

并行 vs 串行

Promise.all() 的一个关键优势是它能够并行处理 Promises。这意味着所有 Promises 都是同时启动的,这与串行执行(一个接一个地执行)形成对比。并行执行可以显著提高程序的效率,特别是在处理多个独立任务时。

快速失败机制

Promise.all() 实现了快速失败机制,即如果其中一个 Promise 失败,则整个 Promise.all() 调用会立即失败。这种机制保证了一致的错误处理,但也意味着在某些场景下需要更谨慎地处理错误。

错误处理策略

由于快速失败的特性,使用 Promise.all() 时应该特别注意错误处理。例如,如果你正在从多个源加载重要数据,一个源的失败不应该阻碍其他数据的处理。这时,你可以在每个单独的 Promise 上使用 .catch() 方法来处理错误,确保每个 Promise 都不会抛出错误。

Promise.all([
  fetchUserInfo

(1).catch(err => ({ error: err.message })),
  fetchOrderHistory(1).catch(err => ({ error: err.message }))
])
.then(([userInfo, orders]) => {
  if (!userInfo.error) {
    console.log('用户信息:', userInfo);
  }
  if (!orders.error) {
    console.log('订单历史:', orders);
  }
})
.catch(error => {
  console.error('未预期的错误:', error);
});

在这个修改后的例子中,即使 fetchUserInfo 或 fetchOrderHistory 中的一个失败了,另一个的结果仍然会被处理。

实际应用场景

Promise.all() 的应用场景非常广泛,以下是一些具体的例子:

1. 资源加载

在网页开发中,你可能需要同时加载多个资源,如图片、JSON 数据和脚本文件。使用 Promise.all() 可以同时启动所有资源的加载,并在全部资源加载完成后执行后续操作。

let imageLoadPromise = loadImage('image.png');
let dataLoadPromise = fetchData('/data.json');
let scriptLoadPromise = loadScript('script.js');

Promise.all([imageLoadPromise, dataLoadPromise, scriptLoadPromise])
    .then(([image, data, script]) => {
        // 所有资源加载完成
    })
    .catch(error => {
        // 处理加载错误
    });

2. 数据库操作

在服务器端应用程序中,当你需要执行多个没有依赖的数据库查询时,Promise.all() 可以并行执行这些查询,提高查询效率。

let userQuery = db.query("SELECT * FROM users WHERE id = ?", [userId]);
let postsQuery = db.query("SELECT * FROM posts WHERE authorId = ?", [userId]);

Promise.all([userQuery, postsQuery])
    .then(([users, posts]) => {
        // 处理查询结果
    })
    .catch(error => {
        // 处理数据库错误
    });

3. API 聚合

在构建一个聚合多个 API 数据的服务时,Promise.all() 可以并行调用这些 API,并在所有调用都完成后聚合这些数据。

let weatherPromise = fetchWeather(cityId);
let newsPromise = fetchNews(topic);

Promise.all([weatherPromise, newsPromise])
    .then(([weather, news]) => {
        // 创建包含天气和新闻的聚合数据
    })
    .catch(error => {
        // 处理 API 调用错误
    });

使用async/await

async/await是在ES2017中引入的,使得异步代码的阅读和编写更像是传统的同步代码。async关键字用于声明一个异步函数,而await关键字则用于等待一个Promise的解决(fulfill)或拒绝(reject)。

同样的操作,使用async/await可以这样写:

async function asyncFunction() {
  try {
    const result = await doSomethingAsync();
    console.log(result);

    const newResult = await doSomethingElseAsync(result);
    console.log(newResult);
  } catch (error) {
    console.error('Something went wrong', error);
  }
}

在这个示例中,await使得JavaScript运行时等待Promise的解决,并且暂停函数的执行,直到Promise被解决。如果Promise被拒绝,错误将被catch块捕获。

总结区别

  • 语法清晰async/await提供了一种更清晰、更直观的方式来处理异步操作。代码看起来更像是同步的,因此更易于理解和维护。
  • 错误处理: 使用async/await时,可以使用传统的try/catch语句进行错误处理,这对于很多开发者来说更加熟悉。
  • 调试友好async/await使得在异步代码中使用断点调试变得更加直观。
  • 基于Promiseasync/await是建立在Promise之上的,实质上它并没有替代Promise的功能,而是提供了一种更简洁的使用方式。

需要注意的是,async/await并不是在所有情况下都替代Promise链。例如,在处理多个并行异步操作时,Promise.all()仍然是一个非常有用的选择。

到此这篇关于js中async/await与Promise的区别的文章就介绍到这了,更多相关js async/await与Promise内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • js本地图片预览实现代码

    js本地图片预览实现代码

    这篇文章主要为大家详细介绍了js本地图片预览实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • 浅述Javascript的外部对象

    浅述Javascript的外部对象

    本文主要对Javascript的外部对象进行介绍,列举了具体实例。便于理解。有需要的朋友可以看下
    2016-12-12
  • 通过循环优化 JavaScript 程序

    通过循环优化 JavaScript 程序

    这篇文章主要介绍了通过循环优化 JavaScript 程序,对于提高 JavaScript 程序的性能这个问题,最简单同时也是很容易被忽视的方法就是学习如何正确编写高性能循环语句。下面我们来学习一下吧
    2019-06-06
  • JavaScript 通过模式匹配实现重载

    JavaScript 通过模式匹配实现重载

    昨天rank同学向我提出一个问题,在实际应用中有些接口需要提供类似于函数重载的功能,以方便开发者组织代码逻辑,简化使用者调用。
    2010-08-08
  • layer弹出子iframe层父子页面传值的实现方法

    layer弹出子iframe层父子页面传值的实现方法

    这篇文章主要介绍了layer弹出子iframe层父子页面传值的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • js 监控iframe URL的变化实例代码

    js 监控iframe URL的变化实例代码

    下面小编就为大家带来一篇js 监控iframe URL的变化实例代码。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • javascript contains和compareDocumentPosition 方法来确定是否HTML节点间的关系

    javascript contains和compareDocumentPosition 方法来确定是否HTML节点间的关

    一个很棒的 blog 文章,是 PPK 两年前写的,文章中解释了 contains() 和 compareDocumentPosition() 方法运行在他们各自的浏览器上。
    2010-02-02
  • JS点击某个图标或按钮弹出文件选择框的实现代码

    JS点击某个图标或按钮弹出文件选择框的实现代码

    本文给大家介绍js点击点击某个图标或按钮弹出文件选择框的实现代码,代码简单易懂,非常不错,感兴趣的朋友可以参考下
    2016-09-09
  • 浅谈js中的三种继承方式及其优缺点

    浅谈js中的三种继承方式及其优缺点

    下面小编就为大家带来一篇浅谈js中的三种继承方式及其优缺点。小编觉得挺不错的,现在就分享给大家,也给大家做个参考,一起跟随小编过来看看吧
    2016-08-08
  • js登录弹出层特效

    js登录弹出层特效

    点击弹出层,点击后弹出一个登录层,在这个层内的内容调用了一个示例页面
    2014-03-03

最新评论