我尝试使用Goodreads API创建nodejs应用程序。当用户搜索书籍时,应用程序将获取查询的goodreads搜索结果,并与本地mongodb数据库匹配,以检查书籍信息是否已在本地数据库中。如果没有,则应用程序将获取每个书籍信息并将其保存到本地数据库以进行缓存。我的代码是这样的 -
goodreads.searchBook(req.query.query, function (err, res) {
if(err) next(err);
var resultObj = JSON.parse(res);
var books = resultObj.GoodreadsResponse.search[0].results[0].work;
// console.log(books[0].best_book[0].id[0]._);
// console.log(books.length);
// show only 6 books
var maxLoop = 6;
if (maxLoop > books.length) {
maxLoop = books.length;
}
var i;
for (i=0; i<maxLoop; i++)
{
var goodreads_id = books[i].best_book[0].id[0]._;
Book.findOne({goodreads_id : goodreads_id}, function(err, res){
if (err) next(err);
if(res) {
console.log('book is already in datastore');
} else {
// ERROR : goodreads_id is always the last one
// OURPUT: example -
// no book found in database for goodreads ID 5
// no book found in database for goodreads ID 5
// no book found in database for goodreads ID 5
// no book found in database for goodreads ID 5
// no book found in database for goodreads ID 5
// no book found in database for goodreads ID 5
console.log('no book found in database for goodreads ID ' + goodreads_id);
goodreads.getBookInfo(goodreads_id, function(err, res){
if (err) next(err);
//console.log(res);
var resObj = JSON.parse(res);
var title = resObj.GoodreadsResponse.book[0].title[0];
console.log(title);
});
}
});
}
});
我想检查每个书籍ID以查看它是否在数据库中,如果没有,则获取单书信息并使用for循环插入数据库。
它应该可以工作,但为什么总是最后一项打印整个for循环?
请帮我理解这个问题。感谢
更新1: goodreads 是我为与goodreads API联系而创建的帮助程序类。这是代码 -
var http = require('http');
var xml2js = require('xml2js');
var parser = new xml2js.Parser();
// defining goodreads class
function goodreads() {
this.url = 'http://www.goodreads.com/';
this.key = '<DEVELOPER KEY>';
}
goodreads.prototype.searchBook = function (query, cb) {
var requestUrl = this.url + 'search/index.xml?q=' + query + '&key=' + this.key;
// console.log('sending query ' + query);
http.get(requestUrl, function(res){
var body = '';
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function () {
parser.parseString(body, function(err, result){
if(err) return cb(err);
var jsonResult = JSON.stringify(result);
return cb(null, jsonResult);
});
})
}).on('error', function (err) {
return cb(err);
});
}
goodreads.prototype.getBookInfo = function(goodreadId, cb) {
var requestUrl = this.url + 'book/show.xml?id=' + goodreadId + '&key=' + this.key;
http.get(requestUrl, function(res){
var body = '';
res.on('data', function(chunk){
body += chunk;
});
res.on('end', function(){
parser.parseString(body, function(err, result){
if (err) return cb(err);
var jsonResult = JSON.stringify(result);
return cb(null, jsonResult);
});
});
}).on('error', function (err) {
return cb(err);
})
}
// take a book object with all information and update local database as needed
goodreads.prototype.updateLocal = function(book, cb) {
// check if the book is already in local database
// if it is in the local database then skip rest of the work and enjoy
// If the book is not in local database then insert the book info to local databse
// download and save the image using the book insert _id file name
// insert author info into author database if its not already inserted
}
var GR = new goodreads();
module.exports = GR;
我在过去几天里学习了nodejs和javascript。我在使用异步编程时遇到了麻烦。
答案 0 :(得分:0)
Book.findOne
是异步的。
当你到达回调函数时,即使对于第一本书,你的循环也已经完成。
要解决此问题,您可以使用promise-returns函数:
goodreads.searchBook(req.query.query, function (err, res) {
if(err) next(err);
var resultObj = JSON.parse(res);
var books = resultObj.GoodreadsResponse.search[0].results[0].work;
// console.log(books[0].best_book[0].id[0]._);
// console.log(books.length);
// show only 6 books
var maxLoop = 6;
if (maxLoop > books.length) {
maxLoop = books.length;
}
// Promise-returning function
var findBookPromise = function(goodreads_id){
return Book.findOne({goodreads_id : goodreads_id}).then(function(res){
if(res) {
console.log('book is already in datastore');
return Promise.resolve();
} else {
// ERROR : goodreads_id is always the last one
// OURPUT: example -
// no book found in database for goodreads ID 5
// no book found in database for goodreads ID 5
// no book found in database for goodreads ID 5
// no book found in database for goodreads ID 5
// no book found in database for goodreads ID 5
// no book found in database for goodreads ID 5
console.log('no book found in database for goodreads ID ' + goodreads_id);
return goodreads.getBookInfo(goodreads_id).then(function(res){
//console.log(res);
var resObj = JSON.parse(res);
var title = resObj.GoodreadsResponse.book[0].title[0];
console.log(title);
return res;
}, next);
}
}, next);
};
var promises = []; // Create an array to store the promises
var i;
for (i=0; i<maxLoop; i++)
{
var goodreads_id = books[i].best_book[0].id[0]._;
promises.push(findBookPromise(goodreads_id));
}
Promise.all(promises).then(function(books){
// Do something with the results
});
});
注意:上述代码未经测试,可能有错误。