【JavaScript】回调、Promise和Async Await

发布时间:2023年12月26日

本文将解释 JavaScript 处理异步操作所依赖的基本概念。这些概念包括 Callback 函数、Promise 和 Async 的使用,以及 Await 在 JavaScript 中处理不同的操作。

在对这三者进行比较之前,我们先简单了解一下同步(阻塞)和异步(非阻塞)。

同步和异步之间的区别

为了便于理解,让我们举一个现实生活中的例子,便于解释异步和同步之间的区别。

想象一下,我们去一家餐馆,一个服务员来到一张桌子前,拿走你的订单,把它送到厨房。让我们将整个过程分为几个步骤

  1. 服务员从表 1 中点餐
  2. 服务员通知厨师菜肴
  3. 将菜肴端至餐桌 2 或从餐桌 2 点餐

餐桌必须等待厨师做一顿饭,然后才能为另一张桌子服务。这就是我们所说的异步或非阻塞架构。在这里,服务员就像一个被分配来处理请求的线程。因此,单个线程用于处理多个请求。

与非阻塞或异步架构相比,我们有阻塞或同步架构。让我们看看它是如何工作的。所以回到餐厅的例子,假设你去另一家餐厅,在这家餐厅,一个服务员被分配给你。他接过你的订单,把它交给厨房。现在他坐在厨房里等着厨师为你准备饭菜,这次他没有做任何其他事情,他只是在等待,在你的饭菜准备好之前,他不会从另一张桌子上接受任何订单。这就是我们所说的同步或阻塞架构。

现在,第一个餐厅示例表示一个异步过程,因为您不必等待,服务员从一张桌子上接单,然后转到下一张桌子接单。而第二个示例餐厅表示同步操作,因为您必须等到资源(在本例中为服务员)可以与您一起继续。这是同步和异步进程之间唯一、最根本的区别。

在 JavaScript 中处理异步代码有不同的方法。这些是回调、promise 和 async/await。

回调

在 JavaScript 中,函数是对象,因此我们可以将对象作为参数传递给函数。

我们以回调函数为例:

function printString(){
   console.log("callback"); 
   setTimeout(function()  { console.log("back"); }, 500); 
   console.log("callback")
}

printString();

如果这是同步代码,我们将遇到以下输出。

callback
back
callback

但是 setTimeout 是一个异步函数,那么上面代码的输出将是:

callback
callback
back

JavaScript 中有一个名为“setTimeout”的内置方法,它在给定的时间段(以毫秒为单位)后调用函数。

换言之,消息函数是在发生某些事情之后(在本例中经过 5 秒后)调用的,而不是在发生之前调用的。

Promise

JavaScript 中的Promise,您可以将其视为现实生活许下的 “承诺” 。当我们在现实生活中做出承诺时,这意味着我们将来会做某事,因为承诺只能为未来做出。

承诺有两种可能的结果:要么你信守诺言,要么不信守诺言。

Promise 的基本原理同样适用于 JavaScript。当我们在 JavaScript 中定义一个 promise 时,它会在时机成熟时被解析,否则它将被拒绝。

promise 用于处理操作的异步结果。JavaScript 被设计为不等待异步代码块完全执行,然后代码的其他同步部分才能运行。使用 Promise,我们可以延迟代码块的执行,直到异步请求完成。这样,其他操作可以不间断地继续运行。

Promise 状态

首先,Promise 是一个对象。Promise 对象有 3 种状态:

  • Pending:初始状态,在 Promise 成功或失败之前。
  • Resolved:已完成承诺
  • Rejected:Failed Promise,引发错误

例如,当我们使用 Promise 从服务器请求数据时,它将处于待处理状态,直到我们收到数据。

如果我们从服务器获取信息,那么 Promise 将被成功解析,但如果我们没有获取信息,那么 Promise 将处于拒绝状态。

创建Promise

首先,我们使用构造函数来创建一个 Promise 对象。promise 有两个参数,一个表示成功(解析),一个表示失败(拒绝):

const myFirstPromise = new Promise((resolve, reject) => { 
    const condition = true;   
    if(condition) {
         setTimeout(function(){
             resolve("Promise 成功!"); 
        }, 500);
    } else {    
        reject('Promise 拒绝!');  
    }
});

在上面的 Promise如果Condition 为 true,解析返回 “Promise 成功 ”的 promise,否则返回错误 “Promise 拒绝”。现在我们已经创建了第一个 Promise,现在让我们使用它。

使用 Promise

要使用上述内容,请创建 Promise,我们用于解决和拒绝。then()catch()

myFirstPromise
.then((successMsg) => {
    console.log(successMsg);
})
.catch((errorMsg) => { 
    console.log(errorMsg);
});
让我们更进一步:
const demoPromise= function() {
  myFirstPromise
  .then((successMsg) => {
      console.log("Success:" + successMsg);
  })
  .catch((errorMsg) => { 
      console.log("Error:" + errorMsg);
  })
}

demoPromise();

在我们创建的承诺条件中,条件是“true”,我们调用 demoPromise(),然后我们的控制台日志显示:

Success: Promise 成功!

因此,如果 promise 被拒绝,它将跳转到该方法,这次我们将在控制台上看到一条不同的消息。catch()

Error: Promise 拒绝!

Async/Await

Await 基本上是 Promise 的语法糖。它使您的异步代码看起来更像是同步/过程代码,这更容易被人类理解。

Async 和 Await 的语法:

async function printMyAsync(){
  await printString("one")
  await printString("two")
  await printString("three")
}

您可以看到,我们为包装函数 printMyAsync 使用了 “async” 关键字。这让 JavaScript 知道我们使用的是 async/await 语法,如果你想使用 Await,这也是必要的。我们可以说 await 只与异步函数一起使用。

await 关键字用于异步函数,以确保异步函数中返回的所有 promise 都是同步的,即。他们互相等待。Await 消除了在 .then().catch() 中使用回调。在使用 async 和 await 时,async 在返回 promise 时被预置,await 在调用 promise 时被预置。try 和 catch 也用于获取异步函数的拒绝值。

让我们举个例子来理解 Promise 的 Async 和 Await:

const helloPromise = function() {
  return new Promise(function(resolve, reject) {
    const message = "hello";

    resolve(message)
  });
}


async function demoPromise() {
  try {
    let message  = await helloPromise();
    console.log(message);

  }
  catch(error){ 
      console.log("Error:" + error.message);
  }
}
demoPromise();

结论

根据我们的用例,我们可以选择这种方法中的任何一种。由于 async/await 封装在 Promise 之上,因此它支持所有与 Promise 相关的功能。因此,在将 callback 与 Promise 进行比较时,Promise 比 callback 具有移动优势。列出其中的几个;

  • 使用 catch 块进行单个错误传播
  • 使用 Promiseasync/await避免回调地狱
  • 使用 Promise.all()实现并行处理。
  • Promise 支持很少其他静态方法,例如(race(), allSettled() 和 any())在比较经常用到的
文章来源:https://blog.csdn.net/qq_43774332/article/details/135216699
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。