2016-09-01 2 views
3
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 문은 실행되지 않고 다른 함수가 값을 반환 할 수있을 때까지 정의되지 않은 변수를 반환합니다.노드 js에서 비동기 콜백을 만드는 방법은 무엇입니까?

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가 정의되지 않은 변수를 반환, 그 결과 실행을 완료 할 수있는 기회를하기 전에 위의 코드에서

  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 문을 실행합니다. 내 앱 (잠재적으로 약속하겠습니까?)에 비동기 기능을 구현해야한다는 것을 알고 있지만, 그렇게하는 방법은 완전히 손실되었습니다!

답변

1

콜백 그래서, 함수 호출에,

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) 

그런 다음 인수 ' 문서'을 받아들이는 콜백 함수를 전달하고 res.json (문서을 실행 : 새로운 기능 서명은 다음과 같이 표시됩니다), db 함수. 예를 들면 :

doc = check_db(req.params[0], shortUrl, db, function(doc){ 
    res.json(doc); 
}); 

: 당신은 단순히 #check_db()에서 #save_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); 
    } 
}); 

. 행운을 빕니다!

0

변경 check_dbsave_db

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); 
     }); 
    }); 
}); 
관련 문제