JS中的异步函数是什么? JS中的异步和等待是什么?

时间:2020-06-04 14:17:35

标签: javascript asynchronous promise async-await es6-promise

此问答旨在明确回答以下问题:

  • 什么是JS中的异步函数?何时以及如何使用它们?
  • JS中的asyncawait关键字是什么,它们与异步函数有何关系?

要遵循答案,必须满足以下先决条件:

  • 对JS异步编程模型的了解
  • ES6 Promise对象的知识

1 个答案:

答案 0 :(得分:5)

简介

JavaScript具有异步模型。每当异步动作完成时,您通常都希望随后执行一些代码。第一个回调是 通常用来解决这个问题。但是,在对具有多个异步元素的代码进行编程时,使用回调会出现问题。因为当您在彼此之间嵌套多个回调时,代码变得很难快速维护。这种反模式称为回调地狱

承诺

Promise解决了嵌套回调中出现的许多问题。许诺的关键特性是可以使用 promise链将它们很好地链接在一起。与回调相比,这使语法更简洁,并且更易于处理错误。这是一个示例:

const randomProm = new Promise((resolve, reject) => {
   if (Math.random() > 0.5) {
     resolve('Succes');
   } else {
     reject('Failure');
   }
  
});

// Promise chain
randomProm
  .then((value) => {
    console.log('inside then1');
    console.log(value);
    return value
}).then((value) => {
    console.log('inside then2');
    console.log(value);
    return value
}).catch((value) => {
    console.log('inside catch');
    console.log(value);
});

异步功能

异步功能建立在promise之上。它们允许更方便地使用Promises。异步函数具有以下属性:

  • async在函数声明/表达式之前将其转换为异步函数。顾名思义,异步函数是异步执行的。
  • 异步功能始终会返回诺言。它将所有返回的值包装在Promise.resolve(returnval)中。但是,当在异步函数中引发未捕获的错误时,它将返回值包装在Promise.catch(returnval)中。
  • 在异步函数中,您可以使用await关键字,该关键字可以在任何承诺之前使用。 await使JS代码执行停止,直到兑现了诺言。也就是说,在执行异步函数中的任何其他代码之前,必须兑现或拒绝承诺。
  • await或者返回已兑现承诺的值,或者在被拒绝承诺的情况下引发错误。我们可以使用常规try-catch来捕获错误。

让我们用一些例子来阐明这一点:

示例1:

const randomProm = new Promise((resolve, reject) => {
    if (Math.random() > 0.5) {
        resolve("Succes");
    } else {
        reject("Failure");
    }
});

// async keyword creates an async function which returns a promise 
async function ansyncExample() {

    try {
        const outcome = await randomProm;
        console.log(outcome);
    } catch (error) {
        console.log(error);
    }

    // This return value is wrapped in a promise
    return 'AsyncReturnVal';
}

// ansyncExample() returns a promise, we can call its corresponding then method
ansyncExample().then((value) => {
    console.log(value);
});

console.log('I get executed before the async code because this is synchronous');

示例2:

// We can use async in function expressions
const randomProm = async () => {
    if (Math.random() > 0.5) {
        // This value is wrapped in Promise.resolve()
        return "Succes";
    } else {
        // This value is wrapped in Promise.reject()
        throw "Failure";
    }
};

// async keyword creates an async function which returns a promise
async function ansyncExample() {
    // randomProm is async fuction which returns a promise which we can await
    return await randomProm();
}

// ansyncExample() returns a promise, we can call its corresponding then/catch method
ansyncExample()
    .then((value) => {
        console.log("Inside then");
        console.log(value);
    })
    .catch((value) => {
        console.log("Inside catch");
        console.log(value);
    });

console.log("I get executed before the async code because this is synchronous");

何时使用异步功能

理论上,您每次使用诺言时都可以使用异步功能。但是,当有多个异步操作返回承诺并相互依赖时,异步功能的功能真正开始发挥作用。

因为异步功能允许我们以同步方式编写基于异步承诺的代码。 代码仍然是异步的,但我们现在可以以同步方式读取。它比promise链更易于阅读和维护,因此扩展性更好(IMO)。

以下是这种可读性的一个示例:

async function ansyncExample() {
    try {
        // 3 async operations which depend on each other
        const firstValue = await firstAsyncFunc();
        const SecondValue = await secondAsyncFunc(firstValue);
        const ThirdValue = await thirdAsyncFunc(SecondValue);
    } catch (error) {
        console.log(error);
    }

    return ThirdValue;
}