【问题标题】:Wait for asynchronous callback function inside synchronous one [duplicate]等待同步内部的异步回调函数[重复]
【发布时间】:2017-04-07 12:57:00
【问题描述】:

我正在使用 Express JSmysql2-node 模块来创建访问 MySQL 数据库的函数

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

我在这个函数中调用了这个函数 - upvoteInArticleFromUser,它需要该用户 ID 的索引才能工作:

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...
    }

我得到了结果:

用户索引:未定义

我了解到 indexOfUserInVotingList 中的return 操作在mysql-query 运行并更新值之前立即执行。

我是否可以强制 indexOfUserInVotingList 等待查询完成并返回结果?

最重要的一点是,我不想把它变成异步函数(尽管这种方法可行):

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

..因为我不想被困在 callbackhell 中,比如:

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...
            }
 }

【问题讨论】:

  • 不可能。如果它是异步的,它会保持异步。不过,您不必使用回调,您可以使用 Promise。

标签: javascript node.js asynchronous callback


【解决方案1】:

由于 node.js 使用的是非阻塞 I/O 模型,所以在涉及 I/O 操作时,如果不等待回调,就无法获取数据。

如果你有“末日金字塔”回调问题,可以尝试使用 Promise。

参考:

【讨论】:

    【解决方案2】:

    图案:

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

    不可能。正如您所发现的,异步函数只是立即返回并且结果未定义。您不能从异步 fcn 返回值

    从异步调用中获取结果的经典设计是通过回调,这看起来很复杂,如果你有嵌套的回调,很快就会变得可怕。

    Promise 就是针对这个问题而开发的。 Promises 允许您编写类似于以下 PSEUDO 代码的代码,从而部分解决了这个问题

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

    虽然不理想,但这允许您编写一种顺序异步代码。如果你还没有,我鼓励你花一些时间在 Promises 上。

    javascript 社区仍然希望 JS 的未来版本将允许以下内容:

    result = wait for asyncFunction(...)
    

    但它似乎还没有出现。

    【讨论】:

    • async/await 不在地平线上,是的。因为它已经在我们的引擎中,并且只等待进入下一个规格修订版!当然,这仍然不能使异步函数同步,它只是简化了异步代码的编写。
    猜你喜欢
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    • 2023-02-10
    • 1970-01-01
    • 2021-03-11
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    相关资源
    最近更新 更多