当前位置: 首页 > 工具软件 > mysql-async > 使用案例 >

回调地狱拯救者 —— 以MySql的 async/await 改造举例

葛昕
2023-12-01

回调地狱拯救者 —— 以MySql的 async/await 改造举例

前言

相信很多使用过Node的人对于回调地狱非常熟悉,回调地狱就是回调函数的不断嵌套造成的,回调地狱造成的后果就是代码的可维护性以及可读性降低。为了解决回调地狱的问题,社区提出了很多解决方案,一开始由Promise的方案,能够把回调函数抽出调用者来减少回调的层级,但并没有解决回调函数所带来的代码阅读困难的问题。这时候提出了 async/await,最先提出 async/await 这种语法的是 C# 语言, ES 以其兼容并蓄的精神迅速将这种优雅的语法吸收进来。通过 async/await 可以将各种回调地狱转化为线性的代码,使得代码更容易阅读,也更容易维护。

这篇文章中所使用的是最原始的mysql模块,通过一步步的改造使其能够使用 async/await 语法写出线性的代码,前置代码如下

const mysql = require('mysql');
const connection = mysql.createConnection({
  host: 'localhost',
  user: 'uers',
  password: 'password',
  database: 'world'
})
connection.connect();

臭名昭著的回调写法

下面的回调写法也就是官方文档中的示例写法。

connection.query('SELECT NAME FROM COUNTRY', function(error, results, fields) {
  if (error) throw error;
  console.log('Get The Results', results);
});

这种写法在回调层级较少的情况下并没有明显弊端,但由于经典Node应用的异步都是通过回调函数实现的,所以但是当功能变得复杂的时候,回调层级一多,代码就会变得非常难看和非常难以维护。现在你可以尝试一下使用回调实现以下功能:当从数据库获取完数据之后,将其写入一个文件,写入成功后向远程服务器发送一个请求,接收到回应之后关闭这个应用。只要是一个有一定审美的程序员,面对这一坨}}}}}}}都会觉得恶心。所以我们需要改进。

Promise 化

Promise是解决}}}}}}的一个方案,把上面的代码用Promise改写之后如下所示

let promiseQuery = new Promise((resolve, reject) => {
  connection.query('SELECT NAME FROM COUNTRY LIMIT 3', (error, results, fields) => {
    if (error) reject(error);
    resolve(results);
  })
})
promiseQuery.then((results, fields) => {
  console.log('The solution is : ', results);
})

Promise可以看作一个管理回调函数的对象,通过.then()方法来传入回调函数,避免了回调函数过多嵌套的问题,变成了链式的.then()。所以Promise并没有完全解决回调地狱的问题,Promise只是将}}}}回调变成了.then.then.then回调,写出来的代码一样不好看,维护性也没有比原来的回调写法好多少。我们需要更加扁平化的写法。

async/await 改造

async/await改造是基于Promise的,保持上面的promiseQuery不变,定义一个async function,使用await获取数据,对数据进行相关操作,然后执行这个async function即可。

async function getData() {
  const value = await promiseQuery;
  return value;
}
(async function displayData () {
  let value = await getData();
  console.log(value);
})()

可以看出在async function里面,回调已经变成了扁平化的代码,现在回看实现我们最初提出的功能:当从数据库获取完数据之后,将其写入一个文件,写入成功后向远程服务器发送一个请求,接收到回应之后关闭这个应用。只要是一个有一定审美的程序员,面对这一坨}}}}}}}都会觉得恶心。所以我们需要改进。通过MySql模块的async/await已经成功砍掉了一对{},只要加以努力,按图索骥,将其它的api使用async/await 进行改造,就可以砍掉一对又一对的{},实现扁平化和易维护的代码。

总结

通过这篇文章,可以了解到,回调地狱形成的原因。然后通过Promise和async/await的改造,将存在回调地狱缺陷的代码改造为扁平化易维护的代码。抛砖引玉,按照文中的思路可以对其它的使用回调函数的代码进行改造。

 类似资料: