【问题标题】:Can I have a recursive JavaScript function inside a $.getJSON function?我可以在 $.getJSON 函数中使用递归 JavaScript 函数吗?
【发布时间】:2015-12-30 16:47:00
【问题描述】:

我有一个深度可变的 JSON 文档。一个例子:

[
    {
        "type": "firsttype",
        "text": {
            "id": "content"
        }
    }
]

我想做的是检索某些键的值,比如text。由于我不知道这些键可能出现在 .JSON 中的什么位置,因此我需要使用递归函数。然后我尝试在 HTML 文件中显示这些键和值。

我这里有一个初步的尝试:

$.getJSON("file.json", function getText (oValue, sKey) {
    links = [];
    if (typeof oValue == "object" || typeof oValue == "array") {
        for (i in oValue) {
            getText (oValue [i], i);
        }
    } else {
        links.push ( "<li id='" + oValue + "'>" + sKey + "</li>" );
    }

    $( "<ul/>", {
        "class": "my-new-list",
        html: links.join( "" )
    }).appendTo( "body" );
});

当我在本地或远程或python -m SimpleHTTPServer 上加载页面时,我没有收到任何错误,页面上也没有任何内容。我究竟做错了什么?我已将所有 JS 包含在 $.getJSON 调用中,因此不会出现异步问题。

将来我还想包含一个正则表达式检查,以便我可以提取具有特定字符串的值,例如/http/。最好的方法是什么?

【问题讨论】:

  • 您能否为我们复制此 JSON 的完整结构?
  • 添加错误处理程序....可能是解析错误或请求失败。我们无法知道,但您需要隔离问题。还要检查浏览器开发工具网络中的实际请求以获取线索
  • @Pointy 我认为如果appendTo jquery 的东西在某种程度上超出了getText 函数并且不是每次都被调用,那么将links 作为一个全局变量会很有意义。
  • @AbbasMashayekh,appendTo jquery 的东西应该getText 之外并且只调用一次。

标签: javascript jquery json regex recursion


【解决方案1】:

我认为您的错误在于变量链接的声明: 它必须在我认为的递归函数之外。 在函数内部每次都会重新初始化。

var links = [];

$.getJSON("file.json", function getText (oValue, sKey) {

         if (typeof oValue == "object" || typeof oValue == "array") {
            for (i in oValue) {
                getText (oValue [i], i);
                }
         } else {
                links.push ( "<li id='" + oValue + "'>" + sKey + "</li>" );
           }

           $( "<ul/>", {
                       "class": "my-new-list",
                       html: links.join( "" )
           }).appendTo( "body" );
});

【讨论】:

    【解决方案2】:

    尝试将您的函数定义移到事件处理程序之外:

     function getText (links, oValue, sKey) {
    
    
             if (typeof oValue == "object" || typeof oValue == "array") {
                for (i in oValue) {
                    getText (links, oValue [i], i);
                    }
             } else {
                 if(oValue && sKey)
                    links.push ( "<li id='" + oValue + "'>" + sKey + "</li>" );
             }
    
               $( "<ul/>", {
                           "class": "my-new-list",
                           html: links.join( "" )
               }).appendTo( "body" );
    };
    
    $.getJSON("file.json", function(data, success){
      var links = [];  
    
      getText (links, data, 0);
    });
    

    如有错误,请随时编辑。

    目的是将链接数组传递给递归函数,并避免将命名函数定义与 getJSON 混合,至少为了清楚起见,并确保您可以传递初始化的 sKey。

    【讨论】:

      【解决方案3】:

      你可以,但在你的情况下你可能不应该

      可以将命名函数作为回调函数传递——这对递归很有用(参见:Using Named Callback Functions In Javascript Methods,Ben Nadel)——但在你的情况下,你可能不应该。

      根据您的示例,在调用递归函数之前和之后,您需要做一些事情。这些事情,例如声明变量和将元素附加到主体,将需要在递归之外发生[一次]。

      因此,传递一个匿名函数作为您的回调,其中包含您的递归函数定义并根据需要调用它。

      在您的情况下,您需要为 JSON 响应数组中返回的每个对象调用它。因此,您也可以将其放在迭代器中。这里为了方便我使用了jQuery的$.each()

      /* FUNCTION THAT MAKES JSON REQUEST */
      function doJsonThing() {
        
        /* BEGIN REWRITE OF OP's EXAMPLE CODE */
        $.getJSON('file.json', function (json) {
          var links = [];
          function getText (key, val) {
            if (typeof val === 'object' || typeof val === 'array') {
              for (i in val) {
                getText(i, val[i]);
              }
            } else {
              links.push('<li id="' + val + '">' + key + ' (' + val + ')</li>' );
            }
          }
          $.each(json, function (key, val) {
            getText(key, val);
          });
          $('<ul/>', {
            "class": "my-new-list",
            "html" : links.join('')
          }).appendTo('body');
        });
        /* END REWRITE OF EXAMPLE CODE */
        
      }
      
      /* THE FOLLOWING IS NOT PART OF THE EXAMPLE,
      // IT IS JUST USED TO SIMULATE A SERVER RESPONSE */
      
      /* BEGIN UNIT TEST */
      // CREATE CLOSURE TO RETURN DUMMY FUNCTION AND FAKE RESPONSE
      function json_response(response) {
        return function (url, success) {
          success(response);
        };
      }
      
      // OVERRIDE $.getJSON WITH DUMMY FUNCTION AND FAKE RESPONSE
      $.getJSON = json_response(
        
        // SIMULATED CONTENTS OF 'file.json'
        $.parseJSON(
          '['
        + '  {'
        + '    "type": "firsttype",'
        + '    "text": {'
        + '      "id": "content"'
        + '    }'
        + '  },'
        + '  {'
        + '    "type": "secondtype",'
        + '    "text": {'
        + '      "id": "other"'
        + '    }'
        + '  }'
        + ']'
        )
      );
      doJsonThing();
      /* END UNIT TEST */
      &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

      【讨论】:

        【解决方案4】:

        由于其他答案涵盖了您应该考虑的大部分内容,我想我只会针对您的实际问题发布解决方案。 :)

        您想遍历任意 JSON 并搜索特定键,并且可能对其值有条件。然后,您要返回指定键的所有值(如果指定,则通过您的条件)。

        假设你有以下 json:

        {
            "hello": "some text",
            "object": {
                "key1": "hello!",
                "key2": "Bye!"
            },
            "array": [{
                "some_key1": "blah blah blah",
                "some_key2": 24
            }, {
                "some_key1": "ghiojd",
                "some_key2": 13
            }],
            "numeric_array": [2, 3, 4, 5]
        }
        

        这个sn-p会在上面的json中搜索some_key1,它的值以blah开头:

        function regexpConditionFactory(regex) {
            return function(value) { return regex.test(value); };
        }
        
        function searchObjectForKey(obj, key, condition, result) {
            if ($.isPlainObject(obj)) {
                if (obj.hasOwnProperty(key)) {
                    if (!condition || ($.isFunction(condition) && condition(obj[key])))
                        result.push(obj[key]);
                }
            }
        
            if ($.isPlainObject(obj) || $.isArray(obj)) {
                for (var k in obj) {
                    if (obj.hasOwnProperty(k))
                        searchObjectForKey(obj[k], key, condition, result);
                }
            }
        }
        
        $.getJSON('file.json', function(data) {
            var res = [];
        
            searchObjectForKey(data, 'some_key1', regexpConditionFactory(/^blah/), res);
        
            $('<ul/>', {
                'class': 'my-new-list',
                'html': res.map(function(value) { return '<li>' + value + '</li>'; }).join('')
            }).appendTo('body');
        });
        &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

        【讨论】:

          猜你喜欢
          • 2017-12-31
          • 2010-09-16
          • 2011-03-05
          • 1970-01-01
          • 2013-01-10
          • 1970-01-01
          • 2022-01-25
          • 2021-12-17
          • 1970-01-01
          相关资源
          最近更新 更多