JavaScript 函数响应和链式承诺

JavaScript function response and chained promises

本文关键字:承诺 函数 响应 JavaScript      更新时间:2023-09-26

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

  • 运行查询以检查要保存的用户是否存在重复的用户;
  • 如果没有重复项,我调用response.success(),这意味着代码可以继续并允许保存新用户;
  • 但是,如果有重复项,我想取existing user,获取一个group对象并将existing user添加到group中。

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

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);
    });
});

在我的测试用例中,查询返回 !user ,因此调用response.success()消息 - 一切都很好。但是,此响应似乎随后会沿着 promise 链向下传输,该 promise 链适用于查询返回user对象的情况。因此,我的函数在第 group.addUnique("contacts", user); 行以错误终止,因为显然,group对象是undefined

如何解决此问题?

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

新代码通过返回existingUser(更新组后)或null来解决此问题。 Null 告诉下一个承诺解析调用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();
    });
}

如您所见,第一个承诺不必解决,因为无论如何都不会使用结果。