用于在Javascript中访问嵌套数据的更好模式

时间:2015-06-17 03:14:49

标签: javascript arrays node.js

我正在编写一些代码,它首先遍历数组,然后进一步遍历原始数组中包含的数组。

我结束了这种奇怪的模式,我正在重复,我确信它没有被优化。在迭代最后一个rssFeeds数组项时,它会将'triggerCallback'的值更改为true。稍后,在遍历item数组时,条件检查triggerCallback是否为true且items数组是否正在遍历其最后一项,此时它会触发回调以在async.js的瀑布模式中使用。

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个不同的itemToPost元素。

[
  {
    "_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"
        }
      }
    ]
  }
]

3 个答案:

答案 0 :(得分:2)

我没有检查过这个,但它与我目前在我的项目中使用的非常相似:

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

正如其他人所提到的,只有在内部循环中有实际的异步方法调用时才需要这个。

答案 1 :(得分:0)

您不需要跟踪最后一项。只需在两个循环退出后调用回调。我还将AbstractRoutingDataSource更改为for循环,因为它们执行得更快。

.forEach

当然,如果您在没有回调的情况下调用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); } ,则调用代码可能如下所示:

countSuccessPosts

您可以将函数重新格式化为:

var successPosts = countSuccessPosts(rssFeeds);

答案 2 :(得分:0)

等等,当你可以同步读取数据时,为什么要使用回调?

在您更新了问题之后,看起来您只是在总结一个问题 数组中元素的数量

这是一个完全同步的版本,用于计算有效itemsToPost集的response.id的数量。

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,因为该函数中发生的所有内容都是同步。