简体   繁体   中英

Doing an sequential operation in Node.js

I built myself a helper-function with node.js to prepare a database, where I currently often do changes in the table structure. So I defined my database structure in an global object "tables" and built the tables using the mssql library via sql-queries. All in all it worked out fine so for. But I now added an process.exit(1) to the end of my init function, which showed me that the interpreter runs through the operations without waiting for sql-execution. How can I modify the code, that the interpreter will execute all steps correctly and quit the program afterwards?

 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); } }); } }) }

You should be able to use async / await for this purpose. If your delete_table / create_table functions return a promise you can await the results of these functions.

I've mocked out the sql functions (as well as process.exit()) for the purpose of demonstration. You can see that the queries will run in order, then the process will exit.

Turns out that sql.connect() and sql.close() will return Promises if no callback is passed. This makes the code much simpler to write.

Node.js code

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);
}

Demonstration Snippet

 /* 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) }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM