- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我对 JavaScript (Node.js) 和 Promises 还很陌生。我目前正在使用 AWS Lambda 和 DynamoDB。
我有一个从数据库异步获取的项目列表(已使用 bluebird Promise API promise 了 AWS SDK。)
对于其中每个项目,我可能需要检索多个子项目(也是异步的),然后对于每个子项目,我必须执行另一个异步操作并确定此异步操作是否成功。
对某个项目完成所有异步操作(即子项目的所有异步操作成功或失败)后,我需要更新数据库中项目的状态(失败/成功。)
这(如下)是我到目前为止所拥有的。你能告诉我我这样做是否正确吗?其中是否存在逻辑错误?可以改进吗?
var doc = require('dynamodb-doc');
var promise = require("bluebird");
var dynamodb = new doc.DynamoDB();
var params = { /* ... */ };
promise.promisifyAll(Object.getPrototypeOf(dynamodb));
dynamodb.queryAsync(params)
.then(function(data) {
var items = data.Items;
var promises = items.map(function(item) {
params = { /* ...*/ };
return dynamodb.queryAsync(params)
.then(function(data2) {
var childItems = data2.Items;
var morePromises = childItems.map(function(device) {
return doAsyncWork()
.then(function success() {
console.log("Success!");
})
.catch(function error(err) {
console.log("Error!");
})
});
return promise.all(morePromises);
})
.then(function() {
// Update status for item in DB
params = { /* ...*/ };
return dynamodb.updateItemAsync(params);
});
});
return promise.all(promises);
})
.then(function() {
var response = { /* ... */ };
context.succeed(response);
})
.catch(function(err) {
context.fail(err);
});
其他一些事情:
对于要完成的一项的所有异步操作,我使用 Promise.all(),从文档中我可以看到,即使一个 promise 被拒绝,后续的 promise 也将被拒绝。我不希望这种情况发生,我希望它继续下去,即使有一个 promise 被拒绝。
同样,对于所有项目,我最终都使用 Promise.all() 等待所有项目完成处理。如果其中一个失败了,其他的就不会被处理了,对吗?我该如何克服这个问题?
有很多嵌套,我该如何改进这段代码?
我需要一种方法来整合所有结果并将其作为响应传递,例如像这样的东西:
{
"Results": [{
"ItemId": " ... ",
"Status": "Success",
"ChildItems": [{
"ChildItemId": " ... ",
"Status": "Success"
/* ...
...
...
*/
}]
}, {
"ItemId": " ... ",
"Status": "Error",
"ChildItems": [{
"ChildItemId": " ... ",
"Status": "Success"
}, {
"ChildItemId": " ... ",
"Status": "Error"
}]
}]
}
我想到的一个解决方案(可能有点难看)是在外部有一个全局对象,然后将结果存储在其中。还有其他优雅的方法吗?
谢谢。
最佳答案
Can it be improved?
自从您使用 Bluebird 以来,您可以改进一些事情。
使用 Bluebird 的 promise.map()
保存代码:
您可以使用 Bluebird 的 promise.map()
来代替 array.map()
后跟 promise.all()
像这样更改代码:
var childItems = data2.Items;
var morePromises = childItems.map(function(device) {
return doAsyncWork()
.then(function success() {
console.log("Success!");
})
.catch(function error(err) {
console.log("Error!");
})
});
return promise.all(morePromises);
对此:
return promise.map(data2.Items, function(item) {
// do something with item
return doAsyncWork();
});
要小心仅记录的 .catch()
处理程序。
如果您处理 Promise 拒绝并且不重新抛出或返回被拒绝的 Promise,则 Promise 状态将从拒绝更改为已完成。
所以,当您使用像这里一样的 .catch()
时:
return dynamodb.queryAsync(params)
.then(function(data2) {
var childItems = data2.Items;
var morePromises = childItems.map(function(device) {
return doAsyncWork()
.then(function success() {
console.log("Success!");
})
.catch(function error(err) {
console.log("Error!");
})
});
return promise.all(morePromises);
})
这将“吃掉”来自 doAsyncWork()
被拒绝的 Promise 的任何错误。有时这就是您想要的(您希望处理错误并继续,就像没有发生任何错误一样),但很多时候您需要错误以某种方式传播回来。您可以记录它,但通过重新抛出错误来传播它:
return dynamodb.queryAsync(params)
.then(function(data2) {
var childItems = data2.Items;
var morePromises = childItems.map(function(device) {
return doAsyncWork()
.then(function success() {
console.log("Success!");
})
.catch(function error(err) {
console.log("doAsyncWork Error: ", err);
//rethrow so error propagates
throw err;
})
});
return promise.all(morePromises);
})
For all async operations of an item to complete I'm using Promise.all(), and from the documentation I can see that if even one promise got rejected the subsequent promises will get rejected as well. I don't want this to happen, I want it to continue even if a single promise is rejected.
在 Bluebird 中,如果您不希望 Promise.all()
在一个 Promise 拒绝时中止,则可以使用 Promise.settle()
而不是 Promise.all()
如果您使用的是 Bluebird 2.x。如果您使用的是 Bluebird 3.x,则在返回您的 Promise 时可以使用 .reflect()
。解释了如何执行此操作 here in the Bluebirds docs 。就我个人而言,我喜欢 Promise.settle()
的工作方式,但必须有一些标准方向的原因来更改它。
There is a lot of nesting, how may I improve upon this code?
您可以链接您正在做的一些事情而不是嵌套。请参阅How to chain and share prior results with Promises用于对多个操作进行排序的多种方法,而无需太多嵌套和累积结果。
关于javascript - 在 Bluebird 中处理多个嵌套异步操作(promises),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34124361/
我正在努力做到这一点 在我的操作中从数据库获取对象列表(确定) 在 JSP 上打印(确定) 此列表作为 JSP 中的可编辑表出现。我想修改然后将其提交回同一操作以将其保存在我的数据库中(失败。当我使用
我有以下形式的 Linq to Entities 查询: var x = from a in SomeData where ... some conditions ... select
我有以下查询。 var query = Repository.Query() .Where(p => !p.IsDeleted && p.Article.ArticleSections.Cou
我正在编写一个应用程序包,其中包含一个主类,其中主方法与GUI类分开,GUI类包含一个带有jtabbedpane的jframe,它有两个选项卡,第一个选项卡包含一个jtable,称为jtable1,第
以下代码产生错误 The nested query is not supported. Operation1='Case' Operation2='Collect' 问题是我做错了什么?我该如何解决?
我已经为 HA redis 集群(2 个副本、1 个主节点、3 个哨兵)设置了本地 docker 环境。只有哨兵暴露端口(10021、10022、10023)。 我使用的是 stackexchange
我正在 Desk.com 中构建一个“集成 URL”,它使用 Shopify Liquid 模板过滤器语法。对于开始日期为 7 天前而结束日期为现在的查询,此 URL 需要包含“开始日期”和“结束日期
你一定想过。然而情况却不理想,python中只能使用类似于 i++/i--等操作。 python中的自增操作 下面代码几乎是所有程序员在python中进行自增(减)操作的常用
我需要在每个使用 github 操作的手动构建中显示分支。例如:https://gyazo.com/2131bf83b0df1e2157480e5be842d4fb 我应该显示分支而不是一个。 最佳答
我有一个关于 Perl qr 运算符的问题: #!/usr/bin/perl -w &mysplit("a:b:c", /:/); sub mysplit { my($str, $patt
我已经使用 ArgoUML 创建了一个 ERD(实体关系图),我希望在一个类中创建两个操作,它们都具有 void 返回类型。但是,我只能创建一个返回 void 类型的操作。 例如: 我能够将 book
Github 操作仍处于测试阶段并且很新,但我希望有人可以提供帮助。我认为可以在主分支和拉取请求上运行 github 操作,如下所示: on: pull_request push: b
我正在尝试创建一个 Twilio 工作流来调用电话并记录用户所说的内容。为此,我正在使用 Record,但我不确定要在 action 参数中放置什么。 尽管我知道 Twilio 会发送有关调用该 UR
我不确定这是否可行,但值得一试。我正在使用模板缓冲区来减少使用此算法的延迟渲染器中光体积的过度绘制(当相机位于体积之外时): 使用廉价的着色器,将深度测试设置为 LEQUAL 绘制背面,将它们标记在模
有没有聪明的方法来复制 和 重命名 文件通过 GitHub 操作? 我想将一些自述文件复制到 /docs文件夹(:= 同一个 repo,不是远程的!),它们将根据它们的 frontmatter 重命名
我有一个 .csv 文件,其中第一列包含用户名。它们采用 FirstName LastName 的形式。我想获取 FirstName 并将 LastName 的第一个字符添加到它上面,然后删除空格。然
Sitecore 根据 Sitecore 树中定义的项目名称生成 URL, http://samplewebsite/Pages/Sample Page 但我们的客户有兴趣降低所有 URL(页面/示例
我正在尝试进行一些计算,但是一旦我输入金额,它就会完成。我只是希望通过单击按钮而不是自动发生这种情况。 到目前为止我做了什么: Angular JS - programming-fr
我的公司创建了一种在环境之间移动文件的复杂方法,现在我们希望将某些构建的 JS 文件(已转换和缩小)从一个 github 存储库移动到另一个。使用 github 操作可以实现这一点吗? 最佳答案 最简
在我的代码中,我创建了一个 JSONArray 对象。并向 JSONArray 对象添加了两个 JSONObject。我使用的是 json-simple-1.1.jar。我的代码是 package j
我是一名优秀的程序员,十分优秀!