在Javascript中访问嵌套数据的更好模式
我正在编写一些代码,首先遍历数组,然后进一步遍历原始数组中包含的数组 我最终得到了这个奇怪的模式,我重复着这个模式,我确信它没有得到优化。在遍历最后一个rssFeeds数组项时,它将“triggerCallback”的值更改为true。稍后,在迭代项数组时,条件检查triggerCallback是否为true,以及items数组是否正在迭代其最后一个项,此时它将触发一个回调以在async.js的瀑布模式中使用在Javascript中访问嵌套数据的更好模式,javascript,arrays,node.js,Javascript,Arrays,Node.js,我正在编写一些代码,首先遍历数组,然后进一步遍历原始数组中包含的数组 我最终得到了这个奇怪的模式,我重复着这个模式,我确信它没有得到优化。在遍历最后一个rssFeeds数组项时,它将“triggerCallback”的值更改为true。稍后,在迭代项数组时,条件检查triggerCallback是否为true,以及items数组是否正在迭代其最后一个项,此时它将触发一个回调以在async.js的瀑布模式中使用 function countSuccessPosts(rssFeeds, cb){
function countSuccessPosts(rssFeeds, cb){
var successCounter = 0;
var triggerCallback = ''
rssFeeds.forEach(function(feed, index, array){
if(index == array.length - 1){
triggerCallback = 'true'
}
feed.itemsToPost.forEach(function(item, itemIndex, itemArray){
if(item.response.id){
++successCounter
}
if(itemIndex == itemArray.length - 1 && triggerCallback == 'true'){
cb(null, rssFeeds, successCounter)
}
})
})
}
构建此模式的最佳方式是什么
数据结构:RssFeeds最多有5个不同的itemsToPost元素
[
{
"_id": "55808127b8f552c8157f74a7",
"name": "",
"imageUrl": "",
"url": "http://www.taxheaven.gr/bibliothiki/soft/xml/soft_law.xml",
"latestDate": "1434056400000",
"endpoints": [
{
"_id": "554f9319bc479deb1757bd2e",
"name": "Wise Individ",
"id": 26413291125,
"type": "Group",
"__v": 0
}
],
"__v": 1,
"itemsToPost": [
{
"title": "Aριθμ.: Υ194/12.6.2015 Τροποποίηση απόφασης ανάθεσης αρμοδιοτήτων στον Αναπληρωτή Υπουργό Οικονομικών Δημήτριο Μάρδα.",
"summary": "Τροποποίηση απόφασης ανάθεσης αρμοδιοτήτων στον Αναπληρωτή Υπουργό Οικονομικών Δημήτριο Μάρδα.",
"url": "http://www.taxheaven.gr/laws/circular/view/id/21113",
"published_at": 1434056400000,
"time_ago": "5 days ago",
"guid": {
"link": "http://www.taxheaven.gr/laws/circular/view/id/21113",
"isPermaLink": "true"
}
}
]
},
{
"_id": "558093013106203517f96d9c",
"name": "",
"imageUrl": "",
"url": "http://www.taxheaven.gr/bibliothiki/soft/xml/soft_new.xml",
"latestDate": "1434489601236",
"endpoints": [],
"__v": 0,
"itemsToPost": [
{
"title": "Taxheaven - Άμεση ενημέρωση - Έγκαιρη επιστημονική κωδικοποίηση - Καινοτομικά εργαλεία. Κωδικοποιήθηκαν όλοι οι νόμοι στους οποίους επιφέρει αλλαγές ο νόμος 4330/2015",
"summary": {},
"url": "http://www.taxheaven.gr/news/news/view/id/24088",
"published_at": 1434494400000,
"time_ago": "about 4 hours ago",
"guid": {
"link": "http://www.taxheaven.gr/news/news/view/id/24088",
"isPermaLink": "true"
}
}
]
}
]
您不需要跟踪最后一项。只要在两个循环退出后调用回调函数。我还将
.forEach
更改为for循环,因为这些循环执行得更快
function countSuccessPosts(rssFeeds, cb) {
var index, itemIndex, feed, item;
for (index = 0; index < rssFeeds.length; index++) {
feed = rssFeeds[index];
for (itemIndex = 0; itemIndex < feed.itemsToPost.length; itemIndex++) {
item = feed.itemsToPost[itemIndex];
if(item.response && item.response.id) {
successCounter++;
}
}
}
cb(null, rssFeeds, successCounter);
}
您可以将函数重新格式化为如下所示:
function countSuccessPosts(rssFeeds) {
var index, itemIndex, feed, item, successCounter = 0;
for (index = 0; index < rssFeeds.length; index++) {
feed = rssFeeds[index];
for (itemIndex = 0; itemIndex < feed.itemsToPost.length; itemIndex++) {
item = feed.itemsToPost[itemIndex];
if(item.response && item.response.id) {
successCounter++;
}
}
}
return successCounter;
}
函数countSuccessPosts(rssFeeds){
var索引,itemIndex,提要,item,successCounter=0;
对于(索引=0;索引
我没有检查这一点,但它与我目前在项目中使用的非常相似:
function countSuccessPosts(rssFeeds, cb){
async.each(rssFeeds, function(eachFeed, outerCallback) {
async(eachFeed.itemToPost, function(eachItem, innerCallback) {
if(item.response.id) {
//Do Something That Is Actually Async. Could be asking the server for success flag, for instance.
doSomethingThatIsActuallyAsync(item.response.id).then(function (err) {
if (!err) {
successCounter = successCounter + 1;
}
innerCallback();
});
} else { //This could be to skip "empty responses" without the need to go to the server, right?
innerCallback();
}
}, outerCallback);
}, function() {
//All done
cb(null, rssFeeds, successCounter);
});
}
正如其他人所提到的,只有在内部循环中有实际的异步方法调用时,才需要它。等等,既然可以同步读取数据,为什么还要使用回调 在你更新了你的问题之后,看起来你只是在总结一个问题 数组中的元素数 下面是一个完全同步的版本,它统计具有有效
响应.id
集的itemsToPost
的数量
function countSuccessPosts(rssFeeds) {
return rssFeeds.reduce(function(sum, x) {
return sum + x.itemsToPost.filter(function(y) {
return !!y.response.id;
}).length;
}, 0);
}
如果需要将其注入异步控制流,则可以轻松地在其上放置包装器
function(rssFeeds, done) {
done(null, rssFeeds, countSuccessPosts(rssFeeds));
}
关键是,
countSuccessPosts
有一个同步API,因为在该函数中发生的一切都是同步的。我现在使用异步作为瀑布模式。您知道哪种方法大致涵盖此功能吗?我可能得潜进去看看能找到什么。。这些不是异步循环吗?那太可笑了。您应该将.forEach
转换为for循环,以便在调用回调函数时立即退出该函数。@PatrickRoberts我不确定库是否适用于这种情况。看起来他正在同步地向下钻取嵌套数据。只是他的countSuccessPosts
函数被异步调用。至少我是这样读的。如果我们有一些示例数据会有所帮助。是的,唯一的异步调用是瀑布中的countSuccessPosts,我基本上只是在这里钻取嵌套数据,我只需要经常重复这个模式,想象有一个更优化的路线可以走。你能不能为这个问题提供一个JSON.stringify(rssFeeds,null,2)
,或者至少是它的一部分,以帮助澄清对象的格式?a)当可以同步访问rssFeeds
时,不需要使用回调。B) 否则,如果//某些代码
具有异步调用,那么您的代码无论如何都会中断,因为cb
在异步函数完成之前被调用。@naomik可能只是因为语法有助于组织和简化他已经像金字塔一样的代码。围绕同步代码编写异步控制是不好的。不要鼓励这样做。JavaScript是单线程的。向函数中添加回调
不会改变这一点。是的,基本上就是这样。我只是在寻找一种更好的模式来循环这些数据,因为我必须经常这样做,当我通过瀑布模式传递此数组并对其进行变异时。@Mayfield先生,我添加了一个快速编辑,以确保item.response.id
在item.response
未定义时不会抛出引用错误。很抱歉,您迟到了一点//有些代码
不是异步的。哎哟,那是因为我花了很多时间来修饰答案,哈哈。别担心,这会发生的。@PatrickRoberts至少他添加了一个附言,说只有在内部循环中有异步方法的情况下才有必要这样做。当然,你的代码比较短,但它比我的解决方案运行得慢,原因是我正在将功能分解为一些小方法,其中许多方法依赖于异步(数据库和网络API调用),并使用异步瀑布模式组织代码并通过rssFeeds数组。嘿,我只是想学习一下。如果我的设计没有得到优化,我一点也不会怀疑。如果您对如何更好地组织我的代码有什么建议,请给出我在上面对我的需求的解释,我很乐意听到@mrmayfield我提供了在瀑布控制代码中使用的同步函数和异步包装器。想想看:仅仅因为你在计算代码异步部分的帖子数量,并不意味着这个数量是异步的。如果要在代码的不同部分调用count函数,会发生什么?使用仅异步的api,它似乎有点崩溃,因为它强制回调,即使它是完全同步的。将函数意图与控制流分开,并在必要时使用包装器。是的,这是一个很好的观点。我明白你的意思,一定会留意我的纯同步方法,并尝试将它们排除在异步工作流之外。谢谢你的帮助!
function(rssFeeds, done) {
done(null, rssFeeds, countSuccessPosts(rssFeeds));
}