当我有自然同步代码但我需要调用一些异步函数时的 JS 基本设计

JS basic design when I have naturaly sync code but I need to call a few async functions

你能帮我理解 javascirpt 异步地狱吗?

我想我遗漏了一些重要的东西 ☹ 问题是 js 示例和互联网上的大多数答案只与代码的一部分有关——一小段代码。但是应用程序要复杂得多。

我不会直接用JS写,因为我更感兴趣的是设计以及如何正确地编写它。

想象一下我的应用程序中的这些功能:

InsertTestData();
SelectDataFromDB_1(‘USERS’);
SelectDataFromDB_2(‘USER_CARS’,’USERS’);
FillCollections(‘USER’,’USER_CARS’);
DoTheWork();
DeleteData();

我没有提供任何功能描述,但我认为根据名称很明显。他们需要按照具体命令执行。想象一下,我需要 运行 a select 进入数据库以获取用户,然后我需要 运行 a select 来获取这些用户的 USER_CARS。所以它必须真的按照这个顺序(考虑其他功能相同)。 问题是需要调用 6 次 Node/Mysql,这是异步的,但我需要特定顺序的结果 。那么我怎样才能正确地做到这一点呢?

这可行: /* 无效代码 我想表达想法并保持简短 */

InsertTestData(
 Mysql.query(select, data, function(err,success)
 {
SelectDataFromDB_1(‘USERS’); --  in that asyn function I will call the next procedure
 }  
 ));

SelectDataFromDB_1 (
 Mysql.query(select, data, function(err,success)
 {
SelectDataFromDB_2(‘USERS’); --  in that asyn function I will call the next procedure
 }  
 ));

SelectDataFromDB_2 (
 Mysql.query(select, data, function(err,success)
 {
FillCollections (‘USERS’); --  in that asyn function I will call the next procedure
 }  
 ));

等..

我可以“轻松”链接它,但这看起来 一团糟。我的意思是真的一团糟。 如果前面的过程完成,我可以使用一些 scheduler/timmers 来安排和测试) 两个都乱七八糟的。

那么,这样做的正确方法是什么;

谢谢, 亚所

如果您使用的是最新版本的 Node,您可以使用 ES2017 的 async/await syntax 来获得看似同步但实际上是异步的代码。

首先,您需要 Mysql.query 的一个版本 returns 一个承诺,这很容易用 util.promisify:

const util = require('util');
// ...
const query = util.promisify(Mysql.query);

然后,将您的代码包装在 async 函数中并使用 await:

(async () => {
    try {
        await InsertTestData();
        await SelectDataFromDB_1(‘USERS’);
        await SelectDataFromDB_2(‘USER_CARS’,’USERS’);
        await FillCollections(‘USER’,’USER_CARS’);
        await DoTheWork();
        await DeleteData();
    } catch (e) {
        // Handle the fact an error occurred...
    }
})();

...您的函数是 async 函数,例如:

async InsertTestData() {
    await query("INSERT INTO ...");
}

请注意 async 包装器中的 try/catch,处理错误是必不可少的,否则如果发生错误,您将收到未处理的拒绝通知(以及未来Node 的版本可能会终止该过程)。 (为什么 "unhandled rejections"?因为 async 函数是 promise 的语法糖;async 函数 returns 是一个 promise。)你可以使用 try/ catch 显示,或在调用结果上使用 .catch 替代:

(async () => {
    await InsertTestData();
    // ...
})().catch(e => {
    // Handle the fact an error occurred
});