JavaScript 函数响应和链式承诺

JavaScript function response and chained promises

我有一个 Parse CloudCode beforeSave 函数,它大致执行以下操作:

为此,我使用链式承诺来使代码更简洁。代码如下:

Parse.Cloud.beforeSave("Contact", function(request, response) {

    var facebookID = request.object.get("facebookID");
    var email = request.object.get("email");

    var queryFb;
    if (facebookID) {
        queryFb = new Parse.Query(Parse.User);
        queryFb.equalTo("facebookID", facebookID);
    }

    var queryEmail;
    if (email) {
        queryEmail = new Parse.Query(Parse.User);
        queryEmail.equalTo("email", email);
    }

    var query;
    if (facebookID && email) {
        query = new Parse.Query.or(queryFb, queryEmail);
    } else if (facebookID) {
        query = queryFb;
    } else {
        query = queryEmail;
    }

    var user;

    query.first().then(function(user) {

        if (!user) {

            response.success();

        } else {

            var groupQuery = new Parse.Query("Group");
            groupQuery.equalTo("title", "ssAll");
            groupQuery.equalTo("owner", request.user);
            return groupQuery.first();
        }

    }).then(function(group) {

        group.addUnique("contacts", user);
        return group.save();

    }).then(function(success) {

        response.error("NOT ERROR - new object was NOT created");

    }, function(error) {

        response.error(error);
    });
});

在我的测试用例中,查询 returns !user,因此调用 response.success() 消息 - 一切正常。但是,此响应似乎随后沿着承诺链传播,这是针对查询 returns 一个 user 对象的情况。因此,我的函数在行 group.addUnique("contacts", user); 上以错误终止,因为显然 group 对象是 undefined.

我该如何解决这个问题?

代码需要一些改进。关键改进是为第二个承诺的解决方案(第二个 then 块)提供一致的起始条件。在没有现有用户的情况下,OP 代码调用 response.success() 。这很好,除了执行仍然落到下一个分辨率,在一个未定义的 group 参数的情况下。

新代码通过返回 existingUser(组更新后)或 null 修复了该问题。 Null 告诉下一个 promise 解析调用 success() 并允许保存继续,否则阻止保存。

另请注意,第一个块的 user 参数与封闭范围中的 var user 冲突 错误。我尝试使用下面的变量命名来突出代码考虑的两种不同类型的用户...

Parse.Cloud.beforeSave("Contact", function(request, response) {
    var facebookID = request.object.get("facebookID");
    var email = request.object.get("email");
    // moved into a function so we can test and deal with it tersely
    findUserByEmailOrFB(email, facebookID).then(function(existingUser) {
        return (existingUser)? addContactToGroupOwnedBy(request.user, existingUser) : null;
    }).then(function(existingUser) {
        if (existingUser) {
            response.error("NOT ERROR - new object was NOT created");
        } else {
            response.success();
        }
    }, function(error) {
        response.error(error);
    });
});

// find the group owned by ownerUser, add contactUser to its contacts return a promise fulfilled as contactUser
function addContactToGroupOwnedBy(ownerUser, contactUser) {
    var groupQuery = new Parse.Query("Group");
    groupQuery.equalTo("title", "ssAll");
    groupQuery.equalTo("owner", ownerUser);
    return groupQuery.first().then(function(group) {
        group.addUnique("contacts", contactUser);
        return group.save().then(function() { return contactUser; });
    });
}

function findUserByEmailOrFB(email, facebookID) {
    var queryFb;
    if (facebookID) {
        queryFb = new Parse.Query(Parse.User);
        queryFb.equalTo("facebookID", facebookID);
    }
    var queryEmail;
    if (email) {
        queryEmail = new Parse.Query(Parse.User);
        queryEmail.equalTo("email", email);
    }
    var query;
    if (facebookID && email) {
        query = new Parse.Query.or(queryFb, queryEmail);
    } else if (facebookID) {
        query = queryFb;
    } else {
        query = queryEmail;
    }
    return query.first();
}

问题是无论检查用户是否成功(还没有这样的用户),你总是在解决第一个承诺。但是,实际上您不必解决承诺。我建议你像这样分开错误案例:

query.first().then(function(user) {
    if (!user) {
        response.success();
    } else {
        addUserToGroup(request.user).then(function() {
            response.error("NOT ERROR - new object was NOT created");
        }, function(error) {
            response.error(error);
        });
    }
});

function addUserToGroup(user) {
    var groupQuery = new Parse.Query("Group");
    groupQuery.equalTo("title", "ssAll");
    groupQuery.equalTo("owner", user);
    return groupQuery.first().then(function(group) {
        group.addUnique("contacts", user);
       return group.save();
    });
}

如您所见,第一个 promise 永远不必解析,因为无论如何都不会使用结果。