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

时间:2015-01-12 06:45:46

标签: node.js mongoose

我从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

因此需要填充“响应”的主要功能不能填充Personne.find({}),因为Personne.find({})在之后完成。处理这个问题的方法是什么?我无法在Web上找到一个非常简单,自我解释的例子(nodejs + mongoose总是给我解决方案,单独使用nodejs,单独使用mongoose,或者使用完整的Web框架,而我只需要一个简单的工作示例)。

2 个答案:

答案 0 :(得分:1)

在数据库调用完成后,您希望执行的任何代码都必须位于数据库调用的回调函数中。所以你不能只是把数据库调用放在你的main函数中 - 你必须将数据库调用之后需要执行的所有代码从代码移到回调函数中。

答案 1 :(得分:1)

如果您希望服务器在您的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/");

});