如何加入同步和异步的世界?

How to join synchronous and asynchronous world?

我刚开始使用 NodeJs,我遇到了一个问题,我相信很多人可能已经解决了。

我有一个基本的 NodeJs Web 服务器,如果找到文件或 404:

var http = require('http'),
    url = require('url'),
    fs = require('fs'),
    mongoose = require('mongoose'),
    fileSystem = require('fs'),
    path = require('path'),
    util = require('util'),
    EventEmitter = require('events').EventEmitter;
var mimeTypes = {
    "html": "text/html",
    "jpeg": "image/jpeg",
    "jpg": "image/jpeg",
    "png": "image/png",
    "js": "text/javascript",
    "css": "text/css"};
var server;
var Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection;

var personneSchema = new Schema({
    nom: String,
    prenom: String
});
var Personne = db.model('Personne', personneSchema);

var personneAdresseSchema = new Schema({
    idPersonne: String,
    idAdresse: String
});
var PersonneAdresse = db.model('PersonneAdresse', personneAdresseSchema);

var adresseSchema = new Schema({
    ligne1: String,
    ligne2: String,
    codePostal: String,
    ville: String
});
var Adresse = db.model('Adresse', adresseSchema);
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
    server = http.createServer(function (request, response) {
        if (request.url=='/persons') {
            console.log('> Persons request');
            /* IMPLEMENTATION PROBLEM HERE */
            var retour='[]';
            retour=retour.substr(0, retour.length-1)+']';
            response.writeHead(200, {
                'Cache-Control': 'no-cache, must-revalidate',
                'Expires': 'Mon, 26 Jul 1997 05:00:00 GMT',
                'Content-type': 'application/json'
            });
            response.end(retour);
            console.log('> end of main function');
            return;
        }
        var uri = url.parse(request.url).pathname;
        var filename = path.join(process.cwd(), uri);
        console.log("> " + filename);
        fs.exists(filename, function(exists) {
            if ((!exists) || (fs.lstatSync(filename).isDirectory())) {
                console.log(">> fichier inexistant : " + filename);
                response.writeHead(200, {'Content-Type': 'text/plain'});
                response.write('404 Not Found\n');
                response.end();
                // Stopper tout traitement :
                return;
            }
            var mimeType = mimeTypes[path.extname(filename).split(".")[1]];
            response.writeHead(200, {'Content-Type':mimeType});

            var fileStream = fs.createReadStream(filename);
            fileStream.pipe(response);
        });
    });
    // Listen on port 8000, IP defaults to 127.0.0.1
    server.listen(8000);
    // Put a friendly message on the terminal
    console.log("Server running at http://127.0.0.1:8000/");
});

问题是:Web 服务器需要在 "main" 函数结束 之前得到一个响应 准备发送。但是,如果您尝试进行猫鼬调用,则它不是同步的。如果在main函数中加入如下代码:

Personne.find({}).select('nom prenom').exec(function (err, p) {
    console.log('> Persons request finished');
});

日志显示如下:

> Persons request
> end of main function
> Persons request finished

所以需要"response"填充的main函数不能用Personne.find({})填充,因为Personne.find({})之后完成了。处理方法是什么?我无法在 Web 上找到一个非常简单、自我解释的示例(nodejs + mongoose 总是给我单独使用 nodejs、单独使用 mongoose 或使用完整的 Web 框架的解决方案,而我只需要一个简单的工作示例)。

您希望在数据库调用完成后执行的任何代码都必须在数据库调用的回调函数中。因此,您不能只将数据库调用放在主函数中——您必须将所有需要在数据库调用之后执行的代码从主函数移到回调函数中。

如果您希望服务器在您的 mongo 查询完成后启动,您可以使用回调:

db.once('open', function () {
     server = http.createServer(function (request, response) {
        Personne.find({}).select('nom prenom').exec(function (err, persons) {
            // Log the result of the query
            console.log(persons) 
            // After the query is executed, you can use the results anywhere else inside your logic
            if (request.url=='/persons') {
                console.log('> Persons request');
                /* IMPLEMENTATION PROBLEM HERE */
                var retour='[]';
                retour=retour.substr(0, retour.length-1)+']';
                response.writeHead(200, {
                    'Cache-Control': 'no-cache, must-revalidate',
                    'Expires': 'Mon, 26 Jul 1997 05:00:00 GMT',
                    'Content-type': 'application/json'
                });
                response.end(retour);
                console.log('> end of main function');
                return;
            }
            var uri = url.parse(request.url).pathname;
            var filename = path.join(process.cwd(), uri);
            console.log("> " + filename);
            fs.exists(filename, function(exists) {
                if ((!exists) || (fs.lstatSync(filename).isDirectory())) {
                    console.log(">> fichier inexistant : " + filename);
                    response.writeHead(200, {'Content-Type': 'text/plain'});
                    response.write('404 Not Found\n');
                    response.end();
                    // Stopper tout traitement :
                    return;
                }
                var mimeType = mimeTypes[path.extname(filename).split(".")[1]];
                response.writeHead(200, {'Content-Type':mimeType});

                var fileStream = fs.createReadStream(filename);
                fileStream.pipe(response);
            });
        });

    });
    // Listen on port 8000, IP defaults to 127.0.0.1
    server.listen(8000);
    // Put a friendly message on the terminal
    console.log("Server running at http://127.0.0.1:8000/");

});