bluebird 承诺每一个都不是 return 最后的结果
bluebird promise each not return the last result
我正在使用 promise.each
循环使用 bookshelfjs
的 2 db 查询,但是角色没有给我结果 -> roles[resource.get('name')] = role.get('name');
,但它给了我对象来自 slect 语句:
var promise = new Promise(
function resolver(resolve, reject) {
var roles = {};
Promise.each(user.relations.relates.models, function(relation){
return Resource.forge({resourceId: relation.get('resourceId')}).fetch().then(function(resource){
return Role.forge({roleId: relation.get('roleId')}).fetch().then(function(role){
roles[resource.get('name')] = role.get('name');
return roles;
}).catch(function(err){
reject({"status":"error", "data": err});
});
}).catch(function(err){
reject({"status":"error", "data": err});
});
}).then(function(roles){
resolve(roles);
});
}
);
return promise;
来自 Promise.each()
的 Bluebird 文档:
Resolves to the original array unmodified, this method is meant to be
used for side effects.
所以,这意味着当你这样做时:
Promise.each(array).then(function(val) {
// iteration finished here
// val is the original array
});
那 val
将是您传入的原始数组,而不是您的 roles
对象。
因为你的 roles
对象在更高的范围内,你可以在你的 .then()
处理程序中删除声明为 roles
的参数并直接引用更高范围的 roles
变量。
您还应该避免使用此处的 promise constructor anti-pattern 并且不要创建新的承诺,而只是 return 您已经拥有的承诺。
你可以这样做:
var roles = {};
return Promise.each(user.relations.relates.models, function (relation) {
return Resource.forge({resourceId: relation.get('resourceId')}).fetch().then(function (resource) {
return Role.forge({roleId: relation.get('roleId')}).fetch().then(function (role) {
roles[resource.get('name')] = role.get('name');
});
}).catch(function (err) {
// repackage how the error is presented into our own object
throw ({"status": "error", "data": err});
});
}).then(function () {
// make the resolved value of the final promise be the roles object
return roles;
});
这个 returned 承诺的解析值将是您的 roles
对象。
变更摘要:
- Return 来自
Promise.each()
的承诺,而不是创建新的承诺(无需在此处创建新的承诺)。
- 让拒绝向上传播,无需手动拒绝更高级别的承诺。
- 在
Promise.each()
的 .then()
处理程序中,删除名为 roles
的声明参数,因为它与更高范围的 roles
对象冲突。
- Return
roles
在那个 .then()
处理程序中,所以它成为你正在 returning 的承诺的解析值。
- 删除内部
.catch()
,因为外部 .catch()
也可以完成它的工作。
- 更改
.catch()
以抛出重新打包的错误值。
- 移除内部的
return roles;
,因为它不需要。 roles
对象在更高范围内始终可用,因此无需使其成为这些内部承诺的解析值(事实上,这样做可能只会造成混乱)。
可能的性能优化。由于 none 的结果取决于先前的结果,看来您可以 运行 所有异步操作并行而不是串行,在这种情况下,您可以将 Promise.each()
替换为 Promise.map()
.
是的,抱歉,我们改变了主意。
在 3.x 中,我们应该使 .each
return 结果而不是原始值,但这对很多人来说破坏了代码,因此我们将其改回并添加一个 mapSeries
.
基本上,只要您使用 each
并关心结果,就使用 .mapSeries
,它完全符合您的期望。如果您可以 运行 这些项目同时使用 .map
,因为它可能会表现得更好。
我正在使用 promise.each
循环使用 bookshelfjs
的 2 db 查询,但是角色没有给我结果 -> roles[resource.get('name')] = role.get('name');
,但它给了我对象来自 slect 语句:
var promise = new Promise(
function resolver(resolve, reject) {
var roles = {};
Promise.each(user.relations.relates.models, function(relation){
return Resource.forge({resourceId: relation.get('resourceId')}).fetch().then(function(resource){
return Role.forge({roleId: relation.get('roleId')}).fetch().then(function(role){
roles[resource.get('name')] = role.get('name');
return roles;
}).catch(function(err){
reject({"status":"error", "data": err});
});
}).catch(function(err){
reject({"status":"error", "data": err});
});
}).then(function(roles){
resolve(roles);
});
}
);
return promise;
来自 Promise.each()
的 Bluebird 文档:
Resolves to the original array unmodified, this method is meant to be used for side effects.
所以,这意味着当你这样做时:
Promise.each(array).then(function(val) {
// iteration finished here
// val is the original array
});
那 val
将是您传入的原始数组,而不是您的 roles
对象。
因为你的 roles
对象在更高的范围内,你可以在你的 .then()
处理程序中删除声明为 roles
的参数并直接引用更高范围的 roles
变量。
您还应该避免使用此处的 promise constructor anti-pattern 并且不要创建新的承诺,而只是 return 您已经拥有的承诺。
你可以这样做:
var roles = {};
return Promise.each(user.relations.relates.models, function (relation) {
return Resource.forge({resourceId: relation.get('resourceId')}).fetch().then(function (resource) {
return Role.forge({roleId: relation.get('roleId')}).fetch().then(function (role) {
roles[resource.get('name')] = role.get('name');
});
}).catch(function (err) {
// repackage how the error is presented into our own object
throw ({"status": "error", "data": err});
});
}).then(function () {
// make the resolved value of the final promise be the roles object
return roles;
});
这个 returned 承诺的解析值将是您的 roles
对象。
变更摘要:
- Return 来自
Promise.each()
的承诺,而不是创建新的承诺(无需在此处创建新的承诺)。 - 让拒绝向上传播,无需手动拒绝更高级别的承诺。
- 在
Promise.each()
的.then()
处理程序中,删除名为roles
的声明参数,因为它与更高范围的roles
对象冲突。 - Return
roles
在那个.then()
处理程序中,所以它成为你正在 returning 的承诺的解析值。 - 删除内部
.catch()
,因为外部.catch()
也可以完成它的工作。 - 更改
.catch()
以抛出重新打包的错误值。 - 移除内部的
return roles;
,因为它不需要。roles
对象在更高范围内始终可用,因此无需使其成为这些内部承诺的解析值(事实上,这样做可能只会造成混乱)。
可能的性能优化。由于 none 的结果取决于先前的结果,看来您可以 运行 所有异步操作并行而不是串行,在这种情况下,您可以将 Promise.each()
替换为 Promise.map()
.
是的,抱歉,我们改变了主意。
在 3.x 中,我们应该使 .each
return 结果而不是原始值,但这对很多人来说破坏了代码,因此我们将其改回并添加一个 mapSeries
.
基本上,只要您使用 each
并关心结果,就使用 .mapSeries
,它完全符合您的期望。如果您可以 运行 这些项目同时使用 .map
,因为它可能会表现得更好。