Search code examples
javascriptnode.jsjquery-callback

solve callback hell on class initializer for node.js


I am using npm package "mssql" In order to open connection. I have to do:

var getOneToken = function (callback) {
    var token = "";

    var connection = new sql.Connection(dbConfig, function(err){   //<-----line 3
        if(err) console.log(err);

        var sqlrequest = new sql.Request(connection);

        sqlrequest.query('select top 1 [accessToken] from AccessToken', function(err, recordset){
            if(err) console.log(err);

            token = recordset[0]['accessToken'];

            connection.close();

            callback(token);
        })
    });
    //how to await the whole block at the top and prevent early execution of code afterwards.
};

The code in this block need to be delayed until database return the result, which is the token. Then further operation can be carried out.

I don't know how to await the code.

Since I tried:

connection = await { new sql.Connection(dbConfig, defer (var err)) }  

It fails. Because tamejs don't allow you to put keyword 'await' over there.

I also use bluebird, asyncawait library, however, it is very hard to flatten the whole block and 'await' on class initialize especially for line 3.

How to deal with this problem ?


Solution

  • function sqlConnect(dbConfig, cb) {
      var conn = new sql.Connection(dbConfig);
      conn.connect(function (err) {
        cb(err, conn);
      });
    }
    

    Usage:

    sqlConnect(dbConfig, function (err, conn) {
      // do your stuff here
    });
    

    Or using tamejs:

    var err, conn;
    await { sqlConnect(dbConfig, defer(err, conn); }
    // do your stuff here
    

    To layout callbacks, you may also want to take a look at async


    Update: If what you want is only avoid callback chain, you don't need to extract a new function for establishing connection. Instead, you can rewrite your function like this:

    var getOneToken = function (dbConfig, cb) {
        var err, recordset;
        var token = "";
    
        var conn = new sql.Connection(dbConfig);
    
        await { conn.connect(defer(err)); }
        if (err) {
            console.log(err);
            cb(token);
            return;
        }
    
        var request = new sql.Request(conn);
        await { request.query('select top 1 [accessToken] from AccessToken', defer(err, recordset)); }
        if (err) {
            console.log(err);
        } else {
            token = recordset[0]['accessToken'];
        }
    
        conn.close();
        cb(token);
    };