简体   繁体   English

不要在顺序链接的承诺中包含q许诺结果

[英]Don't include q promise result in sequentially chained promises

I have the following sequentially chained Q promise that fills in a hierarchy of user->properties->tenants->reminders: 我有以下顺序链接的Q承诺,它填充了用户->属性->租户->提醒的层次结构:

    return getAllUsers()    // get all users of the system
    .then(function(users) {
        return Q.all(users.map(function(user) {
            return getUserProperties(user)  // foreach user of the system get their properties
            .then(function(properties) {
                user.properties = properties;
                return Q.all(properties.map(function(property) {
                    return getPropertyTenants(property) // foreach property get active tenants
                    .then(function(tenants) {
                        property.tenants = tenants;
                        return Q.all(tenants.map(function(tenant) {
                            return getTenantReminders(property, tenant) // foreach tenant get their payment reminders
                            .then(function(reminders) {
                                // if reminders.length == 0 we don't want to include this user
                                tenant.reminders = reminders;
                            });
                        }));
                    });
                }));
            }).thenResolve(user);
        }));
    });

The point of this promise chain is to get all payment reminders for a tenant and then send an email to each user with a list of the tenant reminders (per user). 此承诺链的重点是获取租户的所有付款提醒,然后向每个用户发送一封电子邮件,其中包含租户提醒的列表(每个用户)。 If there are no reminders resolved from getTenantReminders() then ideally the user from the top-level getAllUsers() would not be included in the result. 如果没有从getTenantReminders()解决的提醒,那么理想情况下,顶层getAllUsers()中的用户将不包括在结果中。

I thought about throwing a special error from getTenantReminders().then() handler that goes up the chain and is handled in thenResolve(user) which then does NOT return the user. 我考虑过要从getTenantReminders()。then()处理程序引发一个特殊错误,该处理程序在链上并在thenResolve(user)中处理,然后再不返回用户。 Not sure if this is the proper way. 不知道这是否是正确的方法。

Appreciate any advice. 感谢任何建议。

As Seth says, the key to keeping your sanity here is to avoid the pyramid of doom. 正如塞思所说,保持理智的关键是避免厄运金字塔。 Here is an approach that I believe should work (though obviously I have not tested it): 我认为这是一种可行的方法(尽管显然我尚未对其进行测试):

// Produces a function that takes an array of values as input,
// Applies func() to each of them, and merges the results into a 
// promise for a single array.
// func() is assumed to take a single value as input and 
// return an array or promise for an array
// (X -> Promise<Y[]>) -> (X[] -> Promise<Y[]>)
function applyAllAndMerge(func) {
    return function (values) {
        return Q.all(values.map(func))
        .then(function (arrays) {
            return Array.prototype.concat.apply([], arrays);
        });
    };
}

// returns a promise for an array of all tenant reminders for the
// specified property
// property -> Promise<tenantReminder[]>
function getTenantRemindersForProperty(property) {
    return getPropertyTenants(property)
    .then(applyAllAndMerge(function (tenant) {
        return getTenantReminders(property, tenant);
    }));
}

// returns a promise for an array of all tenant reminders for the 
// specified user
// user -> Promise<tenantReminder[]>
function getTenantRemindersForUser(user) {
    return getUserProperties(user)
    .then(applyAllAndMerge(getTenantRemindersForProperty));
}

// returns a promise for an object containing the specified
// user and all of their tenant reminders
// user -> Promise<{user, tenantReminder}[]>
function getUserAndTenants(user) {
    return getTenantRemindersForUser(user)
    .then(function (reminders) {
        return { user: user, reminders: reminders };
    });
}        

return getAllUsers()    // get all users of the system
.then(function(users) {
    return Q.all(users.map(getUserAndTenants));
})
.then(function (userReminders) {
    // get rid of users with no reminders
    var usersWithReminders = userReminders.filter(function (ur) {
        return ur.reminders.length > 0;
    });

    // use usersWithReminders
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM