【问题标题】:To async, or not to async in node.js?在 node.js 中异步还是不异步?
【发布时间】:2015-05-16 22:45:58
【问题描述】:

我仍在学习 node.js 的技巧,只是想弄清楚我应该推迟什么以及应该执行什么。

我知道通常还有其他与此主题相关的问题,但恐怕没有更相关的例子,我很难“明白”。

我的一般理解是,如果正在执行的代码不平凡,那么异步它可能是一个好主意,以避免它阻碍其他人的会话。显然不止这些,而且回调被提到了很多,而且我不是 100% 说明你为什么不同步所有内容。我还有一些路要走。

下面是我在 express.js 应用中编写的一些基本代码:

app.get('/directory', function(req, res) {
        process.nextTick(function() {
            Item.
                find().
                sort( 'date-modified' ).
                exec( function ( err, items ){
                    if ( err ) {
                        return next( err );
                    }
                    res.render('directory.ejs', {
                        items : items
                    });
                });
        });
    });

我在这里使用process.nextTick() 是否正确?我的理由是,因为它是一个数据库调用,所以必须完成一些实际的工作,这可能会减慢活动会话的速度。还是说错了?

其次,我有一种感觉,如果我推迟数据库查询,那么它应该在回调中,并且在接收到回调响应的情况下,我应该同步进行实际的页面呈现。我只是假设这是因为它似乎是我见过的一些示例中更常见的格式 - 如果这是一个正确的假设,任何人都可以解释为什么会出现这种情况吗?

谢谢!

【问题讨论】:

    标签: node.js mongodb asynchronous express mongoose


    【解决方案1】:

    一般来说,最好的做法是让所有你能做到的事情都是异步的,而不是依赖于同步函数......在大多数情况下,这类似于readFilereadFileSync。在您的示例中,您没有与 i/o 同步执行任何操作。您拥有的唯一同步代码是程序的逻辑(它需要 CPU,因此必须在节点中同步),但相比之下,这些都是很小的事情。

    我不确定Item 是什么,但如果我不得不猜测.find().sort() 的作用是在系统内部构建一个查询字符串。在调用.exec 之前,它实际上不会运行查询(与数据库对话)。 .exec 接受回调,因此它将与数据库异步通信。当该通信完成时,将调用回调。

    在这种情况下,使用 process.nextTick 没有任何作用。这只会延迟其代码的调用,直到下一个不需要做的事件循环。它对同步性没有影响。

    我不太了解您的第二个问题,但如果页面的呈现取决于查询的结果,则您必须将页面的呈现推迟到查询完成 - 您通过在打回来。渲染本身res.render 也可能不是完全同步的。这取决于定义render函数的库的内部机制。

    在您的示例中,next 未定义。相反,您的代码应该如下所示:

    app.get('/directory', function(req, res) {
        Item.
            find().
            sort( 'date-modified' ).
            exec(function (err, items) {
                if (err) {
                    console.error(err);
                    res.status(500).end("Database error");
                }
                else {
                    res.render('directory.ejs', {
                        items : items
                    });
                }
            });
        });
    });
    

    【讨论】:

    • 感谢您的解释 - 对代码的更正非常有帮助!我想询问错误块,但要单独调查以避免“教我节点!” post :) 不过,重要的是,你所做的对我来说很有意义。顺便提一下,我使用的是 mongoose 和 mongodb——这就是 mongoose 查询格式。
    【解决方案2】:

    在这种情况下你用错了,因为.exec() 已经是异步的(你可以从它接受回调作为参数的事实看出)。

    公平地说,nodejs 中大部分需要异步的东西已经是。

    至于页面渲染,如果你需要数据库的结果来渲染页面,而这些结果是异步到达的,你并不能真正同步渲染页面。

    【讨论】:

    • 天哪,我还有更多问题!顺便说一句,当您说它接受回调时,您的意思是您可以在其中放入一个函数(因此return 某事)?还是我也没有完全得到回调?关于页面渲染,这是我没有得到的。所以虽然我可以抽象出数据库调用以供重复使用,但这种结构没有什么问题吗?
    • 有几种方法可以编写异步代码。最低的形式(nodejs 默认使用)是回调的概念。您执行一个操作(如.exec())并传递一个函数以在数据可用时回调(因此,回调)。该操作立即返回,其余的执行继续。在未来的某个时刻,动作实际上完成了,回调被调用,通常带有两个参数:errordata。如果一切顺利完成,error 将为 null 或未定义。
    猜你喜欢
    • 1970-01-01
    • 2016-03-01
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多