2

I'm using Express JS with mysql2-node module to create a function that access MySQL database

indexOfUserInVotingList :

indexOfUserInVotingList: function (voteType, articleID, userID) {
        SQLconnection.connectToServer();
        db = SQLconnection.getConnectionInstance();
        let userIndex;
        switch (voteType) {
            case "upvote":
                db.query('SELECT upVoters FROM article WHERE article.idArticle = ?', [articleID], function (err, rows) {
                    if (err) {
                        throw err;
                    } else {
                        let upvoterArray = rows[0].upVoters;
                        userIndex = upvoterArray.indexOf(userID);
                    }
                });
                break;
            case "downvote":
                db.query('SELECT downVoters FROM article WHERE article.idArticle = ?', [articleID], function (err, rows) {
                    if (err) {
                        throw err;
                    } else {
                        let downvoterArray = rows[0].downVoters;
                        userIndex = downvoterArray.indexOf(userID);
                    }
                });
                break;
            default:
                break;
        }
        return userIndex;
    }

and I call this function inside this one - upvoteInArticleFromUser, which need the index of that userID to work:

upvoteInArticleFromUser: function (articleID, userID, callback) {
        SQLconnection.connectToServer();
        db = SQLconnection.getConnectionInstance();
        let userIndex = this.indexOfUserInVotingList('upvote',articleID,userID);
        console.log("userIndex: "+userIndex);
        // the rest of the code was cut shorted...
    }

And I get the result:

userIndex: undefined

I learnt that return action in indexOfUserInVotingList executed immediately before mysql-query run and update the value.

Is there anyway I can force the indexOfUserInVotingList to wait for the query to finish and return the result ?

The most important point is, I don't want to turn that into async function (although this approach would work):

indexOfUserInVotingList: function (voteType, articleID, userID, callback) {
     //......... 
     //after query from database
     return callback(null,userIndex);
    }

..because I don't want to stuck inside callbackhell, like:

upvoteInArticleFromUser: function (articleID, userID, callback) {
       //.....


       indexOfUserInVotingList('upvote',articleID,userID,function(err,index){
            if(err) throw err;
            else
            {
                this.userIndex = index;
                // the whole remaining code for processing would be nested inside this one...
            }
 }
ThangLeQuoc
  • 2,272
  • 2
  • 19
  • 30
  • 1
    Not possible. If it's async, it stays async. You don't have to use callbacks though, you can use promises. – Bergi Nov 23 '16 at 19:47

2 Answers2

3

The pattern:

result = asyncDoSomething(...);//  returns value

is not possible. The async function just returns immediately and result gets undefined, as you have found out. You can't return a value from an async fcn

The classical design for getting results from an async call is by a callback, which seems convoluted and, if you have nested callbacks, can become horrible in a hurry.

Promises were developed for just this problem. Promises partly solve this problem by allowing you to write code that looks like the following PSEUDO code

promise( executes async fcn and passes result to 'then')
          .then( myFcn(asynResult){use result})
          .then(...

While not ideal, this allows you to write a form of sequential async code. If you haven't already, I encourage you to spend some time with Promises.

The javascript community is still hoping that a future version of JS will allow something like:

result = wait for asyncFunction(...)

But it doesn't seem to be on the horizon yet.

AdamW
  • 186
  • 1
  • 9
  • [`async`/`await`](http://tc39.github.io/ecmascript-asyncawait/) is not on the horizon, yeah. Because it's already in our engines, and only waits to get into the next spec revision! Of course, that still doesn't make async functions synchronous, it just simplifies writing async code. – Bergi Nov 23 '16 at 19:49
1

Since node.js is using non-blocking I/O model, it's not possible to get data without waiting with callback when I/O operations are involved.

If you have "pyramid of doom" callback concern, you can try to use Promise.

Reference:

iKoala
  • 870
  • 4
  • 11