JavaScript 函数响应和链式承诺
JavaScript function response and chained promises
我有一个 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);
});
});
在我的测试用例中,查询 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 永远不必解析,因为无论如何都不会使用结果。
我有一个 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);
});
});
在我的测试用例中,查询 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 永远不必解析,因为无论如何都不会使用结果。