gpt4 book ai didi

javascript - 多个Q.all内部函数?

转载 作者:行者123 更新时间:2023-12-02 17:02:36 25 4
gpt4 key购买 nike

我想向用户发送新书列表。到目前为止,下面的代码运行良好。问题是我不想多次发送一本书,所以我想过滤它们。

当前代码工作正常:

function checkActiveBooks(books) {
var queue = _(books).map(function(book) {
var deferred = Q.defer();

// Get all alerts on given keywords
request('http://localhost:5000/books?l=0&q=' + book.name, function(error, response, body) {
if (error) {
deferred.reject(error);
}

var books = JSON.parse(body);
if (!_.isEmpty(books)) {

// Loop through users of current book.
var userBooks = _(book.users).map(function(user) {

// Save object for this user with name and deals.
return {
user: user,
book: book.name,
books: books
}

});

if (_.isEmpty(userBooks)) {
deferred.resolve(null);
} else {
deferred.resolve(userBooks);
}
} else {
deferred.resolve(null);
}

});

return deferred.promise;

});

return Q.all(queue);
}

但现在我想过滤已经发送的书籍:

function checkActiveBooks(books) {
var queue = _(books).map(function(book) {
var deferred = Q.defer();
// Get all alerts on given keywords
request('http://localhost:5000/books?l=0&q=' + book.name, function(error, response, body) {
if (error) {
deferred.reject(error);
}
var books = JSON.parse(body);
if (!_.isEmpty(books)) {
// Loop through users of current book.
var userBooks = _(book.users).map(function(user) {
var defer = Q.defer();
var userBook = user.userBook.dataValues;
// Check per given UserBook which books are already sent to the user by mail
checkSentBooks(userBook).then(function(sentBooks) {
// Filter books which are already sent.
var leftBooks = _.reject(books, function(obj) {
return sentBooks.indexOf(obj.id) > -1;
});
// Save object for this user with name and deals.
var result = {
user: user,
book: book.name,
books: leftBooks
}
return deferred.resolve(result);
});
return Q.all(userBooks);
} else {
deferred.resolve(null);
}
});
return deferred.promise;
});
return Q.all(queue);
}

但是上面的代码不起作用。它不会停止循环。我认为使用 q.all 两次是有意义的,因为它包含两个循环。但我想我做错了......

最佳答案

首先,您应该始终在最低级别上做出 promise 。你在这里让事情变得复杂并且有多个延期。一般来说,只有在将 API 转换为 Promise 时才应该有 deferreds。 Promise 链并组合,所以让我们这样做吧:)

var request = Q.nfbind(require("request")); // a promised version.

这可以使您在顶部的代码变成:

function checkActiveBooks(books) {
return Q.all(books.map(function(book){
return request('http://.../books?l=0&q=' + book.name)
.get(1) // body
.then(JSON.parse) // parse body as json
.then(function(book){
if(_.isEmpty(book.users)) return null;
return book.users.map(function(user){
return {user: user, book: book.name, books: books };
});
});
});
}

我认为这要优雅得多。

现在,如果我们想通过谓词过滤它们,我们可以这样做:

function checkActiveBooksThatWereNotSent(books) {
return checkActiveBooks(books).then(function(books){
return books.filter(function(book){
return checkSentBooks(book.book);
});
});
}

值得一提的是,Bluebird 库具有针对所有这些的实用方法,例如 Promise#filterPromise#map,这将使此代码更短。

请注意,如果 checkSentBook 是异步的,您需要稍微修改代码:

function checkActiveBooksThatWereNotSent(books) {
return checkActiveBooks(books).then(function(books){
return Q.all(books.map(function(book){ // note the Q.all
return Q.all([book, checkSentBooks(book.book)]);
})).then(function(results){
return results.filter(function(x){ return x[1]; })
.map(function(x){ return x[0]; });
});
});
}

就像我说的,使用不同的库,这看起来会好得多。 Bluebird 中的代码如下所示,速度也快了两个数量级,并且具有良好的堆栈跟踪和未处理拒绝的检测。为了乐趣和荣耀,我加入了 ES6 箭头和简写属性:

var request = Promise.promisify(require("request"));

var checkActiveBooks = (books) =>
Promise.
map(books, book => request("...&q=" + book.name).get(1)).
map(JSON.parse).
map(book => book.users.length ?
book.users.map(user => {user, books, book: book.name) : null))

var checkActiveBooksThatWereNotSent = (books) =>
checkActiveBooks(books).filter(checkBookSent)

我觉得这更好。

关于javascript - 多个Q.all内部函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25565174/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com