在.settle()(或等效项)中,从Promises数组中断开

Break out of an array of Promises while in .settle() (or equivalent)

本文关键字:Promises 数组 中断 断开 settle      更新时间:2023-09-26

我们目前正在使用bluebird v2.9.8,无法升级到v3以实现兼容性(目前,但可能也没有解决方案)。

我们过去使用过.settle(),但遇到了一个情况,即我们有一组users,映射到promises,我们需要确认特定字段是否为true

如果存在false的单一病例,则无需继续。如果它们都是true,那就意味着我们已经执行了所有的promises

Promise.settle()将执行全部,等待全部完成。

同样,我们的目标是在获得false后立即突破。


原来还有一段代码调用了一个额外的Promise来从数据库获取更多信息。因此,重写为使用Promise.all():

var accessPromises = users.map(function (user) {
    return new Promise(function(resolve, reject) {
        if (user.userId == matchingUserId) {
            return resolve(true);
        } else if (user.type && user.type == matchingType) {
            return resolve(true);
        } else {
            // See if this user is one of your connections
            DB.getAdditionalUserInfo()
            .then(function (additionalUserInfo) {
                if (additionalUserInfo.a == user.userId)
                    return resolve(true);
                else
                    return reject(false);
            })
            .catch(function (err) {
                return reject(false);
            });
        }
    });
});
Promise.all(accessPromises).then(function (accessResults) {
    if (accessResults.every(result => result)
        res.ok();
    else
        res.notFound();
})
.catch(function (err) {
    res.notFound();
});

这确实允许我们在第一次拒绝后中断,但任何已经启动的额外DB调用无论如何都会完成。

这将起作用,并使我们能够更快地将响应返回到客户端,但仍会留下一些浪费的处理。

使用Promise.all()而不是Promise.settle()

Promise.all()将在通过的第一个承诺被拒绝时完成,而不会等待其他承诺。因此,您可以测试您的条件,然后拒绝,然后Promise.all()也会立即拒绝。

另一方面,无论结果如何,Promise.settle()都将等待所有请求完成。

如果您展示了一些有代表性的代码,我们可以更具体地帮助您。

下面是一个虚构的例子:

function getUser(name) {
    // code that returns a promise whose fulfilled value is a user object
}
function getUserTestField(name) {
    return getUser(name).then(function(user) {
        if (!user.someField) {
            return Promise.reject({status: false});
        } else {
            return user;
        }
    }, function(err) {
        return Promise.reject({errCode: err});
    });
}
var promises = ["bob", "ted", "alice"].map(function(name) {
    return getUserTestField(name);
});
Promise.all(promises).then(function(users) {
    // all users had field set to true
}, function(err) {
    if (err.status === false) {
        // at least one user has the field set to false
    } else {
        // some other type of error here
        console.log(err.errCode);
    }
});