掌握Promise和async/await编写优雅的异步代码

个人主页:《爱蹦跶的大A阿》

当前正在更新专栏:《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》

​ 

目录

✨ 前言

✨ 正文

一、简介、回调

什么是回调函数

回调函数示例

异步回调

小结

二、Promise

什么是Promise

基本用法

Promise链

Promise对象方法

总结

三、使用 promise 进行错误处理

reject处理

try...catch

未处理的rejections

总结

✨ 结语


✨ 前言

        对于任何重要的网页应用来说,能够高效地处理异步操作是非常关键的。异步编程不仅可以避免网站卡顿,也可以大幅提升用户体验。

        JavaScript语言中处理异步最常见的方式就是Promise和async/await。它们都可以帮助我们优雅地编写非阻塞、异步代码。

        本文将详细介绍Promise的用法,以及async/await如何帮助我们解决"回调地狱"问题。通过学习这些知识,你可以在项目中使用它们编写出更简洁、合理的异步代码。

✨ 正文

一、简介、回调

什么是回调函数

回调函数(callback)是一种常见的JavaScript编码模式。简单来说,回调函数就是一个通过函数参数传递到另一个函数中的函数,它会在包含它的函数内部被调用。

回调函数允许我们将某些任务的执行委托给另一个函数。这使得代码更加灵活、模块化。

回调函数示例

function greeting(name) {
  alert('Hello ' + name);
}

function processUserInput(callback) {
  var name = prompt('Please enter your name.');
  callback(name);
}

processUserInput(greeting);

这里,processUserInput函数接收另一个函数greeting作为参数。在processUserInput内部,它调用了greeting,使得greeting成为一个回调函数。

这样我们就将greeting任务的执行“委托”给了processUserInput。

异步回调

回调函数的一大用途是异步编程。

比如,有一个需要长时间运行的函数fetchData(),我们可以像下面这样使用回调:


function fetchData(callback) {
  // 获取数据,此处使用定时器模拟异步
  setTimeout(() => {
    callback('Done');
  }, 1000);
}

function processData(data) {
  console.log(data);
}

fetchData(processData);

fetchData会在任务完成后异步地调用processData。这避免了同步方式中需要等待的情况。

小结

  • 回调函数通过参数传递,在包含它的函数内调用
  • 异步操作会在完成后调用回调,避免同步方式的等待问题
  • 回调是JavaScript中常见的编码方式,可以写出灵活的异步代码

掌握回调函数是学习JavaScript的重要一步。它可以帮助我们更好地处理异步场景,编写非阻塞代码。

二、Promise

什么是Promise

Promise是JavaScript中处理异步操作的一种模式。它代表了一个还未完成,但预期将来会完成的操作。

Promise有以下几个特点:

  • 异步操作成功时,触发resolve回调
  • 异步操作失败时,触发reject回调
  • Promise状态一旦改变就不能再变(从Pending到Resolved或Rejected)

基本用法

使用Promise,我们可以把异步操作像这样封装起来:

let promise = new Promise(function(resolve, reject) {

  // 异步操作

  if(/* 操作成功 */){
    resolve(value); 
  } else {  
    reject(error);
  }

});

 然后使用.then方法接收成功结果,.catch方法处理错误:

promise.then(
  result => {
    // 操作成功
  },
  error => {
    // 操作失败  
  } 
);

Promise使我们可以更优雅地处理异步操作的结果。

Promise链

Promise的好处之一是能够链式调用.then

当一个Promise成功返回结果时,我们可以在.then中创建并返回一个新的Promise,这样就能形成一个Promise链:

let promise = fetchData();

promise
  .then(result1 => {
    return processResult1(result1); 
  })
  .then(result2 => {
    return processResult2(result2);
  });

Promise链允许我们将异步操作编排成洋葱圈式的流程。

Promise对象方法

Promise对象上还有一些其他有用的方法:

  • Promise.resolve() - 将现有的值包装成一个resolved状态的Promise对象
  • Promise.reject() - 创建一个rejected Promise
  • Promise.all() - 将多个Promise包装成一个新的Promise

等等。

总结

  • Promise代表一个异步操作的最终完成或失败的结果
  • 可以链式调用.then.catch处理结果
  • Promise对象提供了许多静态方法如resolvereject

Promise是编写异步JavaScript代码很重要的模式,需要好好学习掌握。

三、使用 promise 进行错误处理

Promise可以HELP我们优雅地处理异步操作。但是合理处理Promise中可能出现的错误也很重要。

reject处理

当Promise操作失败时,会调用reject回调:

let promise = new Promise((resolve, reject) => {
  // ...
  if(error) {
    reject(error); 
  }
});

在PromiseUsage链中,我们应该用.catch处理reject案例:

promise
  .then(result => {···})
  .catch(err => {
    // 处理错误 
  });

 .catch.then类似,但它只处理reject的情况。

try...catch

如果我们在.then/catch处理函数中抛出异常,需要用try...catch捕获:

promise
  .then(result => {···})
  .catch(err => {
    
    throw new Error('Error!');
    
  })
  .then(() => {}, err => { // (*)
  
    try {
      throw err;
    } catch {
      handleError(err);    
    }
  
  })

这里我们在(*)处增加了.then调用,并在其中使用try...catch,来处理前面步骤中可能出现的错误。

未处理的rejections

如果没有处理reject case,Promise状态将变成rejected,这对于发现问题很有帮助。

我们可以在Promise链的末尾加上 .catch 作为“兜底”的保护:

promise
  .then(...)
  .then(...)
  .catch(err => { // 处理所有rejections
    ···
  });

 未处理的rejections也可以被全局事件unhandledrejection捕捉到。

总结

  • 使用.catch处理reject case
  • 在Promise内部需要加try...catch捕获所有情况
  • 兜底.catch可以避免未处理的rejections
  • unhandledrejection处理全局未捕获情况

合理处理Promise错误非常重要,可以避免许多难以发现的bug。

✨ 结语

        Promise和async/await为JavaScript带来了编写异步代码的现代方式。使用它们可以让我们的代码更加简洁、直观、避免回调嵌套问题。

        如果你之前主要依靠回调函数来处理异步,是时候升级你的异步编程技能了。将Promise和async/await应用到你的项目中,一定能带来质的飞跃,让代码异步处理能力大大提高。

        希望本文能让你对这两者有一个全面而深入的理解。活用它们,定能成为一个更出色的JavaScript开发者!

你可能感兴趣的:(JavaScript保姆级教程,前端,javascript)