JavaScript 如何链式调用异步函数

JavaScript 如何链式调用异步函数

JavaScript是单线程的异步编程语言。因此,一些耗时的操作,如I/O、数据库访问、网络调用等,会异步执行,以避免中断JS线程中的其他事务。这可以通过异步代码(如promise或async函数)来实现。异步函数很酷,但它们的执行时间是不确定的,这有时会在存在相互依赖的两个异步函数时创建问题。

注意: 本文将使用ES2015+的特性,如async函数、箭头函数等。然而,同样的结果也可以使用较旧的ES特性来实现。

示例1: 为了帮助我们解决这个问题,我们有三个异步函数(黑盒函数)。

Javascript

<script> 
  async function getUserData() { 
      console.log('Fetching data');      
  } 
  
  async function cleanUserData(userData) { 
      console.log('Cleaning data');       
  } 
  
  async function saveToDataBase(userData) { 
      console.log('Saving to DB');      
  } 
  const userData = getUserData(); 
  const cleanedData = cleanUserData(userData); 
  saveToDataBase(cleanedData); 
</script> 

输出: 这些是异步函数,它们的执行时间并不总是相同。因此,这些函数可以以任何可能的顺序运行。下面是一个可能的输出。

Cleaning data
Saving to DB
Fetching data

有两种方法可以运行这些函数并强制函数执行的顺序。

1. 使用 Promise 的 .then()

Javascript

<script> 
async function getUserData() { 
      console.log('Fetching data');      
  } 
  
  async function cleanUserData(userData) { 
      console.log('Cleaning data');       
  } 
  
  async function saveToDataBase(userData) { 
      console.log('Saving to DB');      
  } 
  getUserData() 
    .then((userData) => cleanUserData(userData))       
    .then((cleanedData) => saveToDataBase(cleanedData))  
    .then(() => console.log('All work done'))         
 </script>

输出:

Fetching data
Cleaning data
Saving to DB
All work done

这很好并且起作用,但有时会导致回调地狱,可能在看到代码时影响你的心情(开个玩笑)。

**2. 使用 **async/ await :

有一种更清晰的方法来完成同样的事情,使用 await 关键字等待函数执行完成。 await 只能在 async 函数内部工作。所以,我们需要将其包裹在一个包装函数中。

Javascript

<script> 
  async function getUserData() { 
      console.log('Fetching data');      
  } 
  
  async function cleanUserData(userData) { 
      console.log('Cleaning data');       
  } 
  
  async function saveToDataBase(userData) { 
      console.log('Saving to DB');      
  } 
  async function cleanAndSaveUserData() { 
    const userData = await getUserData(); 
    const cleanedData = await cleanUserData(userData); 
    await saveToDataBase(cleanedData); 
      
    console.log('All work done'); 
  } 
  
  cleanAndSaveUserData(); // does all the work 
  
</script> 

输出:

Fetching data
Cleaning data
Saving to DB
All work done

注意: 为简单起见,本文不涵盖链式async()函数的错误处理。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程