首页 > 解决方案 > 在 Node.js 中执行顺序操作

问题描述

我用 node.js 为自己构建了一个辅助函数来准备一个数据库,我目前经常在其中对表结构进行更改。因此,我在全局对象“表”中定义了我的数据库结构,并通过 sql-queries 使用 mssql 库构建了表。总而言之,结果很好。但是我现在在我的 init 函数的末尾添加了一个 process.exit(1),这表明解释器在不等待 sql 执行的情况下运行这些操作。如何修改代码,解释器将正确执行所有步骤并随后退出程序?

const tables = {

    table_name_1: {
        "key1": "nvarchar(25)",
        "key2": "int",
        "..": "bit",
    },
    table_name_2: {
        "key1": "int",
        "key2": "nvarchar(50)",
        "..": "int",
    },
    table_name_3: {
        "key1": "int",
        "key2": "int",
        "..": "int",
    }
    
}

init_environment();

function init_environment() {

    console.log("Init started...");

    delete_table(Object.keys(tables));
    create_table(Object.keys(tables));

    console.log("Init finished");
    process.exit(1);
}

function delete_table(tables_to_delete) {

    sql.connect(SQL_CONFIG, function () {

        for (var i = 0; i < tables_to_delete.length; i++) {

            var request = new sql.Request();
            var query = "DROP TABLE " + tables_to_delete[i];

            request.query(query, function (err, recordset) {
                if (err) {
                    console.log(err);
                } 
            });

        }

    })

}

function create_table(tables_to_create) {

    sql.connect(SQL_CONFIG, function () {

        for (var i = 0; i < tables_to_create.length; i++) {

            var request = new sql.Request();

            var query = "CREATE TABLE " + tables_to_create[i] + " (id INT IDENTITY(1,1) PRIMARY KEY, ";

            for (var key in tables[tables_to_create[i]]) {
                query += key + " " + tables[tables_to_create[i]][key] + ", ";
            }

            query += ")";

            request.query(query, function (err, recordset) {
                if (err) {
                    console.log(err);
                }
            });

        }

    })

}

标签: javascriptsqlnode.jsasynchronousasync-await

解决方案


您应该能够为此目的使用async / await 。如果您的 delete_table / create_table 函数返回一个承诺,您可以等待这些函数的结果。

出于演示的目的,我已经模拟了 sql 函数(以及 process.exit())。您可以看到查询将按顺序运行,然后进程将退出。

事实证明,如果没有通过回调,sql.connect() 和 sql.close() 将返回 Promises。这使得代码更容易编写。

Node.js 代码

const tables = {

    table_name_1: {
        "key1": "nvarchar(25)",
        "key2": "int"
    },
    table_name_2: {
        "key1": "int",
        "key2": "nvarchar(50)",
    },
    table_name_3: {
        "key1": "int",
        "key2": "int"
    }
    
}

init_environment();

async function init_environment() {

    console.log("Init started...");

    await delete_table(Object.keys(tables));
    await create_table(Object.keys(tables));

    console.log("Init finished");
    process.exit(1);
}

async function delete_table(tables_to_delete) {
    await sql.connect(SQL_CONFIG);
    for (var i = 0; i < tables_to_delete.length; i++) {
        var query = "DROP TABLE IF EXISTS " + tables_to_delete[i];
        await runQuery(query);
    }
    await sql.close();
}

async function create_table(tables_to_create) {
    await sql.connect(SQL_CONFIG);
    
    for (var i = 0; i < tables_to_create.length; i++) {

        var query = "CREATE TABLE " + tables_to_create[i] + " (id INT IDENTITY(1,1) PRIMARY KEY, ";

        for (var key in tables[tables_to_create[i]]) {
            query += key + " " + tables[tables_to_create[i]][key] + ", ";
        }

        query += ")";
        
        await runQuery(query);
    }
    await sql.close();
}

function runQuery(query) {
     console.log("runQuery: Running query: " + query);
     var request = new sql.Request();
     return request.query(query);
}

演示片段

/* Mock code */
const SQL_CONFIG = "Some config"
const sql = { 
   connect(config) {
       return new Promise(resolve => setTimeout(resolve, 1000));
   },
   close() { 
       return new Promise(resolve => setTimeout(resolve, 1000));
   }
}

class Request {
    query(query) {
        return new Promise(resolve => setTimeout(resolve, 500, null, {}));
    }
}

sql.Request = Request;

process = { 
    exit() {
        console.log("Exiting process...");
    }
}

/* End Mock code */

const tables = {

    table_name_1: {
        "key1": "nvarchar(25)",
        "key2": "int",
        "..": "bit",
    },
    table_name_2: {
        "key1": "int",
        "key2": "nvarchar(50)",
        "..": "int",
    },
    table_name_3: {
        "key1": "int",
        "key2": "int",
        "..": "int",
    }
    
}

init_environment();

async function init_environment() {

    console.log("Init started...");

    await delete_table(Object.keys(tables));
    await create_table(Object.keys(tables));

    console.log("Init finished");
    process.exit(1);
}

async function delete_table(tables_to_delete) {
    await sql.connect(SQL_CONFIG);
    for (var i = 0; i < tables_to_delete.length; i++) {
        var query = "DROP TABLE " + tables_to_delete[i];
        await runQuery(query);
    }
    await sql.close();
}

async function create_table(tables_to_create) {
    await sql.connect(SQL_CONFIG);
    
    for (var i = 0; i < tables_to_create.length; i++) {
        let lastQuery = i === tables_to_create.length -1;

        var query = "CREATE TABLE " + tables_to_create[i] + " (id INT IDENTITY(1,1) PRIMARY KEY, ";

        for (var key in tables[tables_to_create[i]]) {
            query += key + " " + tables[tables_to_create[i]][key] + ", ";
        }

        query += ")";
        
        await runQuery(query);
    }
    await sql.close();
}

function runQuery(query) {
     console.log("runQuery: Running query: " + query)
     var request = new sql.Request();
     return request.query(query)
}


推荐阅读