javascript - 展平嵌套回调

标签 javascript arrays node.js callback

这是我编写的一个回调(为了解决这个问题而稍微修改/简化),用于处理一些对象数据。

  function (err, data) {
    var rv;
    if (data && data.result instanceof Array) {
      rv = data.result.map(function (value) {
        if (value && value.track_contributions instanceof Array) {
          return value.track_contributions.map(function (innerValue) {
            if (innerValue && innerValue.track) {
              return innerValue.track.mid;
            }
          });
        }
      });
      // flatten nested arrays
      rv = [].concat.apply([], rv);
    }
    console.log(rv);
  };

这是我正在处理的对象的样子:

{
  "result": [
    {
      "type": "/music/artist",
      "track_contributions": [
        {
          "track": {
            "mid": "/m/015rm3l"
          }
        },
        {
          "track": {
            "mid": "/m/0nm2km"
          }
        },
        {
          "track": {
            "mid": "/m/010ksbq"
          }
        },
        ...
      ]
    }
  ]
}

我希望回调的返回值如下所示:

[ '/m/015rm3l',
  '/m/0nm2km',
  '/m/010ksbq',
  ...
]

我的代码工作得很好,但我觉得所有的嵌套都是代码味道。

我应该如何使这种类型的代码更扁平、更具可读性和可维护性以及所有这些很棒的东西? promise ?一些 lodash 类型的实用程序?还有别的事吗?以上都是吗?

最佳答案

这是一个我认为更容易理解和维护的版本,没有重复的代码,因为它使用带有回调的通用遍历来添加数据结构的细节:

function process(err, data) {
    var rv = [];
    function doObject(obj, key, callback) {
        if (obj[key] && obj[key] instanceof Array) {
            obj[key].forEach(function(value) {
                callback(value);
            });
        }
    }
    doObject(data, "result", function(result) {
        doObject(result, "track_contributions", function(item) {
            if (item.track && item.track.mid) {
                rv.push(item.track.mid);
            }
        });

    });
    console.log(rv);
}

在不更改您正在使用的基本算法的情况下,您可以初始化 rv 并将结果直接推送到 rv 中,而不是创建随后必须展平的子数组。

function process(err, data) {
    var rv = [];
    if (data && data.result instanceof Array) {
        data.result.forEach(function(value) {
            if (value && value.track_contributions instanceof Array) {
                value.track_contributions.forEach(function(innerValue) {
                    if (innerValue && innerValue.track) {
                        rv.push(innerValue.track.mid);
                    }
                });
            }
        });
    }
    console.log(rv);
}

由于您在每个级别查找的属性名称都不同,因此使用递归来避免重复代码并不高效或容易(尽管这是一个选项)。

这是一个两级递归算法,尽管我认为增加的复杂性实际上并不值得。如果您的深度超过 2 个级别或任意数量的级别,则可能更有意义:

function process(err, data) {
    var rv = [];
    function doArray(item, key1, key2) {
        if (item && item[key1] instanceofArray) {
            item[key1].forEach(function(value) {
                if (key2) {
                    doArray(value, key2);
                } else if (value && value.track.mid) {
                    rv.push(value.track.mid);
                }
            });
        }
    }
    doArray(data, "result", "track_contributions");
    console.log(rv);
}

关于javascript - 展平嵌套回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27050901/

相关文章:

c - 如何将数组作为函数调用?

javascript - AngularJS $http.delete 和 $window.location.reload()

node.js - AWS SES : how to send a large amount of emails (> 10000 at a time)

javascript - ts-node 和自定义加载器

javascript - ajax在wordpress中发送400错误请求错误

javascript - JavaScript 代码错误

javascript - 循环函数和数组: javascript

c++ - 无法转换大括号括起来的初始值设定项列表

javascript - 将键值对(数组中的值)添加到数组中的特定对象

javascript - 将嵌套对象映射到数组