Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/448.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在NodeJS中创建异步回调?_Javascript_Node.js_Express_Asynchronous - Fatal编程技术网

Javascript 如何在NodeJS中创建异步回调?

Javascript 如何在NodeJS中创建异步回调?,javascript,node.js,express,asynchronous,Javascript,Node.js,Express,Asynchronous,下面的res.json语句在其他函数有机会返回值之前运行并返回一个未定义的变量 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 Goog

下面的res.json语句在其他函数有机会返回值之前运行并返回一个未定义的变量

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语句在GET请求下面定义的函数有机会完成执行之前执行,结果res.json返回一个未定义的变量。我知道我必须在我的应用程序中实现异步功能(可能是承诺?),但我完全不知道如何做到这一点

检查\u db
保存\u db
更改为异步

            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();
    });
}
然后像这样使用:

function check_db(longUrl, shortUrl, db, cb){
    db.collection('sites').findOne({
        'longUrl': longUrl, 
        'shortUrl': shortUrl
    }, function(err, doc){
        if(err){
            console.log(err);
            process.nextTick(function(){cb(err)});
        }else if(doc){
            console.log('This site already exists on the database');
            process.nextTick(function(){cb(null, doc)});
        }else{
            save_db(longUrl, shortUrl, db, cb);
        }
    });

}

function save_db(longUrl, shortUrl, db, cb){
    db.collection('sites').insert({
        'longUrl': longUrl, 
        'shortUrl': shortUrl
    }, function(err, doc){
        db.close();
        process.nextTick(function(){cb(err, doc)});
    });
}

回调只是函数调用中的一个参数,所以

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);
       }
       check_db(req.params[0], shortUrl, db, function(err, doc){
          if(err) return res.json(err);
             res.json(doc);
       });
   });
});
表现得像

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);
调用#googleUrl.shorten()后会立即调用#res.json(),就像调用#foo()后会立即调用#bar()

您的回调函数:

foo(a, b);
bar();
异步执行,这意味着它不会中断常规控制流。当您需要延迟执行像#res.json(doc)这样的语句时,您必须确保它的执行也脱离常规控制流。为此,您需要在#check_db()#save_db()中接受回调参数。新函数签名如下所示:

function(err, shortUrl){
   if(err){
       console.log(err);
   }else{
       console.log(shortUrl);
   }
   doc = check_db(req.params[0], shortUrl, db);
}

然后将接受参数“doc”并执行res.json(doc)的回调函数传递给db函数。例如:

function check_db(longUrl, shortUrl, db, callback)
注意:您只需将“回调”传递给#save_db()#check_db()

最后,在异步函数完成执行后,调用回调,而不是返回值。例如:

doc = check_db(req.params[0], shortUrl, db, function(doc){
  res.json(doc);
});
我已经将对#save_db()的更改留给了您。祝你好运

doc = check_db(req.params[0], shortUrl, db, function(doc){
  res.json(doc);
});
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);
    }
});