承诺进入.then()和.catch()

时间:2017-11-23 14:37:29

标签: javascript promise

希望你们一切都很好:)。我正在开发一款应用程序,用意大利面条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

3 个答案:

答案 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)

结束重写上面的代码,问题就消失了。 意大利面怪物代码是一种不好的做法,应该避免使用。