2016-11-15 111 views
0

我有下面的代碼(不按預期工作):node.js:如何返回一個回調函數的值?

var express = require('express') 
var app = express() 
var MongoClient = require('mongodb').MongoClient; 
var url = 'mongodb://localhost:27017/interviews'; 

app.get('/', function(req, res){ 
    var result = get_document(res); 
    res.send(result // show the results of get document in the browser //) 
    console.log("end"); 
}); 

app.listen(3000, function(req, res) { 
    console.log("Listening on port 3000"); 
}); 

function get_document() { 
    MongoClient.connect(url, function(err, db) { 
    var col = db.collection('myinterviews'); 
    var data = col.find().toArray(function(err, docs) { 
     db.close(); 
     return docs[0].name.toString(); // returns to the function that calls the callback 
    }); 
    }); 
} 

函數「get_document」應該返回存儲在「myinterviews」收集的文件。問題是,'return docs [0] ...'這一行返回給col.find(這是調用回調的函數),而不是app.get(...)中的變量'result'。

你知道如何讓文件返回'result'變量嗎?

回答

1

你應該看看承諾api。

「get_document」函數應該返回一個新的promise,並帶有resolve和reject函數回調(成功/失敗)。

所以,它應該看起來有點像這樣:

var express = require('express') 
var app = express() 
var MongoClient = require('mongodb').MongoClient; 
var url = 'mongodb://localhost:27017/interviews'; 

app.get('/', function(req, res){ 
var result = get_document(res).then(function (doc) { 
    res.send(doc); 
}); 
// show the results of get document in the browser //) 
console.log("end"); 
}); 

app.listen(3000, function(req, res) { 
    console.log("Listening on port 3000"); 
}); 

function get_document() { 

    return new Promise(

    function (resolve, reject) 
     MongoClient.connect(url, function(err, db) { 
     var col = db.collection('myinterviews'); 
     var data = col.find().toArray(function(err, docs) { 
     db.close(); 
     resolve(docs[0].name.toString()); // returns to the function that calls the callback 
    }); 
    }); 
); 
} 
+0

很好的答案。謝謝。至於承諾 - 你不覺得bluebird.promisify(bluebirdjs.com/docs/api/promise.promisify.html)更好嗎? – CrazySynthax

+0

Yeap,它可能是。我沒有使用它,所以我不能根據經驗評論:)。看看這個:http://softwareengineering.stackexchange.com/questions/278778/why-are-native-es6-promises-slower-and-more-memory-intensive-than-bluebird – Alex

1

get_document功能異步運行。撥打MongoClient.connect()可能需要一些時間,因此無法立即返回。要返回數據庫調用後的值,必須將回調傳遞給get_document函數。所以它應該看起來像這樣:

var express = require('express') 
var app = express() 
var MongoClient = require('mongodb').MongoClient; 
var url = 'mongodb://localhost:27017/interviews'; 

app.get('/', function(req, res){ 
    var result = get_document(function(result) { 
     res.send(result); 
     console.log("end"); 
    }); 
}); 

app.listen(3000, function(req, res) { 
    console.log("Listening on port 3000"); 
}); 

function get_document(done) { 
    MongoClient.connect(url, function(err, db) { 
    var col = db.collection('myinterviews'); 
    var data = col.find().toArray(function(err, docs) { 
     db.close(); 
     done(docs[0].name.toString()); // returns to the function that calls the callback 
    }); 
    }); 
} 
+1

或者,你可以使用Promises:https ://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise < - 你可以在這裏閱讀它們 –

+1

很好的答案。謝謝。至於諾言 - 你不覺得bluebird.promisify(http://bluebirdjs.com/docs/api/promise.promisify.html)更好嗎? – CrazySynthax

+0

無可否認,我沒有使用bluebird.promisify作爲'Promise'一直能夠讓我超越線條。我將閱讀文檔並讓你知道我的想法:) –