var express = require('express');
var GoogleUrl = require('google-url');
var favicon = require('serve-favicon');
var mongo = require('mongodb').MongoClient;
var app = express();
var db;
var googleUrl = new GoogleUrl({key: 'AIzaSyB5i1sdnt6HwzrvsPTBu0FbPiUZrM_BCsk'});
var PORT = 8080;
mongo.connect('mongodb://localhost:27017/url-shortener', function(err, newDb){
if(err){
throw new Error('Database failed to connect');
} else{
console.log('Successfully connected to MongoDB on port 27017');
}
db=newDb;
db.createCollection('sites', {
autoIndexID: true
});
});
app.use(favicon(__dirname+'/public/favicon.ico'));
app.get('/new/*', function(req, res){
var doc;
console.log('This is the url: '+req.params[0]);
googleUrl.shorten(req.params[0], function(err, shortUrl){
if(err){
console.log(err);
}else{
console.log(shortUrl);
}
doc = check_db(req.params[0], shortUrl, db);
});
下面的res.json语句运行并返回一个未定义的变量,然后其他函数才有机会返回值。
res.json(doc);
});
app.listen(process.env.PORT, function(){
console.log('Express listening on: '+PORT);
});
function check_db(longUrl, shortUrl, db){
db.collection('sites').findOne({
'longUrl': longUrl,
'shortUrl': shortUrl
}, function(err, doc){
if(err){
console.log(err);
}if(doc){
在执行以下语句之前,将先执行res.json语句,然后可以返回一个值。
console.log('This site already exists on the database');
return doc;
}else{
save_db(longUrl, shortUrl, db);
}
});
}
function save_db(longUrl, shortUrl, db){
db.collection('sites').insert({
'longUrl': longUrl,
'shortUrl': shortUrl
}, function(err, doc){
if(err){
throw err
}else{
console.log(doc);
}
db.close();
});
}
在上面的代码中,res.json语句在GET请求下面定义的函数有机会完成执行之前执行,结果res.json返回一个未定义的变量。我知道我必须在我的应用程序中实现异步功能(可能会实现吗?),但是我完全不知道该怎么做!
回调只是函数调用中的一个参数,因此
googleUrl.shorten(req.params[0], function(err, shortUrl){
if(err){
console.log(err);
}else{
console.log(shortUrl);
}
doc = check_db(req.params[0], shortUrl, db);
});
res.json(doc);
表现就像
foo(a, b);
bar();
您对#googleUrl.shorten()的调用之后立即是对#res.json()的调用,就像对#foo()的调用随后是对#bar()的调用一样。
您的回调函数:
function(err, shortUrl){
if(err){
console.log(err);
}else{
console.log(shortUrl);
}
doc = check_db(req.params[0], shortUrl, db);
}
以异步方式执行,这意味着它不会中断常规控制流。当需要推迟执行#res.json(doc)之类的语句时,必须确保它的执行也从常规控制流中删除。为此,您需要在#check_db()和#save_db()中都接受一个回调参数。新的函数签名将如下所示:
function save_db(longUrl, shortUrl, db, callback)
和
function check_db(longUrl, shortUrl, db, callback)
然后将一个回调函数传递给您的db函数,该回调函数接受参数doc并执行res.json(doc)。例如:
doc = check_db(req.params[0], shortUrl, db, function(doc){
res.json(doc);
});
注意:您只需将“回调”从#check_db()传递到#save_db()即可。
最后,在异步函数完成执行后,调用回调,而不是返回值。例如:
db.collection('sites').findOne({
'longUrl': longUrl,
'shortUrl': shortUrl
}, function(err, doc){
if(err){
console.log(err);
}if(doc){
console.log('This site already exists on the database');
callback(doc);
}else{
save_db(longUrl, shortUrl, db, callback);
}
});
我已经将对#save_db()的更改留给了您。祝你好运!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句