希望你们一切都很好:)。我正在开发一款应用程序,用意大利面条Promise代码打了一个角落里的石头,让我感到困惑。必须提到这是我在Promise的第一次尝试(试图放弃回调地狱:))
我正在使用node.js并需要一个模块将Goodreads API中的数据传输到应用程序的其他部分,以便我可以使用它。我创建了一个对象,我在模块中导出一个函数返回一个Promise链。
问题在于我在应用程序的主要部分调用此模块。如果我创建的Goodreads模块api以Promise的.reject()结尾,则调用.then()和.catch()。代码中的更多内联注释希望它有所帮助。
这是我的代码: goodreads_module.js:
let goodreads = {
getItem: function(path) {
if (typeof path == 'object') {
return path._;
} else {
return path;
}
},
// Get the book id needed for further serach of book language on different api end-point
getBookId: function(word) {
let self = this;
logger.log(logger.info, 'Getting book process started!');
// Query for GoodRead search
const query_book = {
q: word,
page: '',
type: 'title'
};
logger.log(logger.info, 'Seaching by word: ' + query_book.q);
return new Promise((resolve, reject) => {
// Searching for book using
// @param: query_book
if (typeof query_book !== 'undefined') {
// directly resolve with the promise
return resolve(grclient.searchBooks(query_book));
} else {
let reason = 'No word to search for';
return reject(reason);
}
})
.then((result) => {
let search = result.search,
rating,
book_id,
random_nr,
ratings_count,
count = 0;
if(parseInt(search['total-results']) == 0){
return false;
}
if (parseInt(search['total-results']) !== 0 && !Array.isArray(search.results.work)) {
logger.log(logger.info, 'Book data is:\n' + JSON.stringify(search.results.work));
rating = self.getItem(search.results.work.average_rating)
ratings_count = self.getItem(search.results.work.ratings_count);
book_id = search.results.work.best_book.id._;
}
if (parseInt(search['total-results']) > 1 && Array.isArray(search.results.work)) {
random_nr = Math.floor(Math.random() * search.results.work.length);
logger.log(logger.info, 'Book data is:\n' + JSON.stringify(search.results.work[random_nr]));
rating = self.getItem(search.results.work[random_nr].average_rating)
ratings_count = self.getItem(search.results.work[random_nr].ratings_count);
// If the book grabed has the rating lower than 3.8 grab another book
do {
random_nr = Math.floor(Math.random() * search.results.work.length);
rating = self.getItem(search.results.work[random_nr].average_rating)
ratings_count = self.getItem(search.results.work[random_nr].ratings_count);
logger.log(logger.warn, 'New book data is:\n' + JSON.stringify(search.results.work[random_nr]));
count++;
if (count == 10) {
break;
}
} while (rating <= 3.8 && ratings_count <= 5 || rating <= 3.8 && ratings_count >= 5 || rating >= 3.8 && ratings_count <= 5)
if (count == 10) {
return false;
}
console.log(count);
logger.log(logger.info, 'Book rating / rating rount ' + JSON.stringify(rating) + "/" +JSON.stringify(ratings_count));
// Grab the book id when all rules are met
book_id = search.results.work[random_nr].best_book.id._;
}
if (rating <= 3.8 && ratings_count <= 5 || rating <= 3.8 && ratings_count >= 5 || rating >= 3.8 && ratings_count <= 5) {
return false;
}
return parseInt(book_id);
})
},
// Finally get the book using the book id and return book data in a object containg author ,title and url.
getBook: function(word) {
let self = this;
return new Promise((resolve, reject) => {
self.getBookId(word).then((result) => {
if (typeof result == 'boolean') {
let reason = 'Book id invalid';
return reject(reason);
}
return resolve(result);
})
})
.then((result) => {
logger.log(logger.info, 'Check language for book id: ' + result);
return new Promise((resolve, reject) => {
grclient.showBook(result).then((response) => {
let data = response.book;
let lang = data.language_code;
logger.log(logger.info, 'Book language is ' + JSON.stringify(lang));
if (lang == 'eng' || lang == 'en-US' || lang == 'en-GB' || lang == 'English' || lang == 'english' || lang == 'en-US') {
let book = {
title: data.title,
author: data.authors.author.name ? data.authors.author.name : data.authors.author[0].name,
url: data.url
}
return resolve(book);
} else {
let reason = 'Language is not english';
return reject(reason);
}
})
})
})
},}
main.js:
goodreads.getBook(goodreads.word()).then((data)=>{
logger.log(logger.info, "Got the book! Continue with tweeting process");
// use data here
})
你能帮我看一下我做错了什么,因为.catch()方法应该是main.js中唯一一个没有短暂调用.then()的人吗?我应该如何将这一承诺联系起来?
谢谢, ZAPO
答案 0 :(得分:1)
你有点滥用承诺,除非你做异步的事情,否则你不需要每次都创造新的承诺。
如果你想要一个新的履行承诺,只需返回一个值,如果你想要一个新的被拒绝的承诺,则抛出。
new Promise((res, reject) => {
res(true);
}).then(val => {
return false;
}).then(val => console.log(val)); // false
new Promise((res, reject) => {
res(true);
}).then(val => {
throw "foo";
}).catch(err => console.log(err)); // "foo"
关于承诺的另一个重点是,如果您返回一个承诺,生成的新承诺将根据返回的承诺得到解决/拒绝,因此代码的开头可以简化为
return new Promise((resolve, reject) => {
if (typeof query_book !=='undefined') {
// directly resolve with the promise
return resolve(grclient.searchBooks(query_book));
} else {
let reason = 'No word to search for';
return reject(reason);
}
});
答案 1 :(得分:0)
.then
和.catch
可能存在问题。根据mdn,承诺。then需要两次回调,一次是成功,另一次是拒绝。如果您在then
之后指定了一个问题,那么您的代码可能会在then
的首次回调中出现问题。 e.g。
someAPICall()
.then(() => {//if code breaks here it'll go in catch too})
.catch(() => {//can come here})
但是如果你想编写承诺拒绝的代码。您必须提供then
第二个回调:
someAPICall()
.then(() => {
//success
}, () => {
//rejection
});
对不起,我没有读过你的整个代码,这也可能是这不是主要原因。如果答案没有帮助请评论。希望有所帮助。
答案 2 :(得分:0)
结束重写上面的代码,问题就消失了。 意大利面怪物代码是一种不好的做法,应该避免使用。