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获取当月最后一天实例代码,有需要的朋友可以参考一下
    2013-11-11
  • 得到form下的所有的input的js代码

    得到form下的所有的input的js代码

    得到form下的所有的input的方法有很多,在本文为大家介绍下使用form 的集合对象elements,从而得到value,需要的朋友可以参考下
    2013-11-11
  • 解决layui弹出层layer的area过大被遮挡的问题

    解决layui弹出层layer的area过大被遮挡的问题

    今天小编就为大家分享一篇解决layui弹出层layer的area过大被遮挡的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-09-09
  • Bootstrap基本组件学习笔记之分页(12)

    Bootstrap基本组件学习笔记之分页(12)

    这篇文章主要为大家详细介绍了Bootstrap基本组件学习笔记之分页,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • ES6 迭代器 Iterator使用总结

    ES6 迭代器 Iterator使用总结

    ES6引入了Iterator(迭代器)接口,用于顺序访问可迭代对象,Iterator接口提供统一的访问接口,并通过for...of循环供消费,本文给大家介绍ES6 迭代器 Iterator使用总结,感兴趣的朋友跟随小编一起看看吧
    2025-02-02
  • 用ES6写全屏滚动插件的示例代码

    用ES6写全屏滚动插件的示例代码

    本篇文章主要介绍了用ES6写全屏滚动插件的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • 24个ES6方法解决JS实际开发问题(小结)

    24个ES6方法解决JS实际开发问题(小结)

    这篇文章主要介绍了24个ES6方法解决JS实际开发问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • JavaScript Canvas实现图片局部放大镜效果

    JavaScript Canvas实现图片局部放大镜效果

    这篇文章主要为大家详细介绍了如何使用JavaScript Canvas实现图片局部放大镜效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-03-03
  • 关于RxJS Subject的学习笔记

    关于RxJS Subject的学习笔记

    这篇文章主要介绍了关于RxJS Subject的学习笔记,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • 关于JavaScript中var声明变量作用域的推断

    关于JavaScript中var声明变量作用域的推断

    这个问题其实之前困扰了我很久。如今终于想明白了,特来分享,如果有错误的地方,请帮忙指正,我会随时回来修正滴。
    2010-12-12

最新评论