Javascript 如何使用回调递归地构建一个列表并遍历子级?

Javascript 如何使用回调递归地构建一个列表并遍历子级?,javascript,jquery,asynchronous,recursion,html-lists,Javascript,Jquery,Asynchronous,Recursion,Html Lists,我不确定如何构建这个列表(它是一个字符串),然后作为一个完整的字符串返回。 我已经完成了上一期的工作,但我觉得这一期真的让我很烦恼。buildItem()应该遍历该项,然后递归地构建一个列表,同时从另一个回调获取总成本。我知道它是异步工作的 buildItem(data, function(html){ $('#nestable ol').append(html); }); 应该附加通过在整个文件中附加而创建的“最终”html字符串 function buildItem(item, c

我不确定如何构建这个列表(它是一个字符串),然后作为一个完整的字符串返回。 我已经完成了上一期的工作,但我觉得这一期真的让我很烦恼。buildItem()应该遍历该项,然后递归地构建一个列表,同时从另一个回调获取总成本。我知道它是异步工作的

buildItem(data, function(html){
    $('#nestable ol').append(html);
});
应该附加通过在整个文件中附加而创建的“最终”html字符串

function buildItem(item, callback) {
    getTotalCost(item, function(totalCost) {
        var html = "<li class='dd-item' data-id='" + item.id + "' data-email='" + item.email + "' data-title='" + item.corporateTitle + "' data-name='" + item.firstName + " " + item.lastName + "' id='" + item.id + "'>";
        if (item.children && item.children.length > 0) {
            html += "<ol class='dd-list'>";
            $.each(item.children, function (index, sub) {
                buildItem(item, function(subHtml){
                    html += subHtml;
                })
            })
            html += "</ol>";
        }
        html += "</li>";
        callback(html);
    });
}
不应该工作,因为javascript是异步的。我只是不知道如何从递归函数返回?如果我要做这样的事

buildItem(item, function(subHtml){
    callback(subHtml);
})
您将获得重复的值,因为您将拥有起始值及其子项,但由于您也将其回调,因此您将获得起始值之外的子项。所以看起来像

1
     a
     b
     c
     d
     e
a
b
c
d
e
那么,找到解决方案的最佳方法是什么?我正在考虑创建另一个函数,假设是一个返回html的buildChild(sub),但是异步的同样问题也会出现,返回将是未定义的。我读过一些线程,其中可以使用回调处理异步值,但我不确定如何使用递归

getTotalCost是另一个回调函数,它应该没有太大意义,我无意中删除了该行,但我只需要数据库中的totalCost

function getTotalCost(item, callback) {
    $.ajax({
        dataType: "json",
        url: "/retrieveData.do?item=" + item.email,
        success: function(data) {
            var totalCost = 0;
            for (var i = 0; i < data.length; i++) {
                totalCost += parseFloat(data[i].cost);
            }
            callback(totalCost);
        }
    });
}
函数getTotalCost(项,回调){ $.ajax({ 数据类型:“json”, url:“/retrieveData.do?item=“+item.email, 成功:功能(数据){ var总成本=0; 对于(变量i=0;i您可以使用和简化此过程:

异步函数getTotalCost(项){ const data=wait Promise.resolve($.ajax({ 数据类型:“json”, url:“/retrieveData.do?item=“+item.email” })); 返回数据.减少((acc,next)=>acc+next.cost,0); } 异步函数buildItem(item){ const totalCost=等待getTotalCost(项目); 让html=`
  • ”; 如果(item.children&&item.children.length>0){ html+=''; for(const childItem of item.children){ html+=等待构建项(childItem); } html+=“”; } html+=“
  • ”; 返回html; } 不幸的是,并非所有浏览器都支持异步函数,因此您必须使用它来传输代码


    我还添加了一些新的ES6功能:,和。

    如果通过同步执行器执行代码,您可以将缓慢的ajax请求与逻辑和递归混合使用

    第一步。将逻辑编写为同步逻辑,并将其放入函数:

    function process(item) {
        function getTotalCost(item) {
            var data = jQueryGetJSON(nsynjsCtx, "/retrieveData.do?item=" + item.email).data;
            var totalCost = 0;
            for (var i = 0; i < data.length; i++) {
                totalCost += parseFloat(data[i].cost);
            }
            return totalCost;
        };
    
        function buildItem(item) {
            const totalCost = getTotalCost(item);
            var html = "<li class='dd-item' data-id='" + item.id + "' data-email='" + item.email + "' data-title='" + item.corporateTitle + "' data-name='" + item.firstName + " " + item.lastName + "' id='" + item.id + "'>";
    
            if (item.children && item.children.length > 0) {
                html += '<ol class="dd-list">';
                for (var i=0; i<item.children.length; i++)
                    html += buildItem(item.children[i]);
                html += "</ol>";
            }
            html += "</li>";
            return html;
        };
    
        return buildItem(item);
    };
    

    请参阅此处的更多示例:

    我想我可以,但我使用的是IE11,传输的代码看起来不容易维护。我希望在我已有的基础上有一个解决方案。@CHom你是什么意思?你不需要维护传输代码——它只用于浏览器。我正在开发一个大型网站,作为这个项目的开发人员之一,我不想对某个特定部分的代码编写方式做出如此大的改变。如果我不在这个项目中,我愿意使用它。@CHom,那么您可以使用。这是否意味着除了使用另一个库之外,没有可行的解决方案?只是想知道。
    async function getTotalCost(item) {
      const data = await Promise.resolve($.ajax({
        dataType: "json",
        url: "/retrieveData.do?item=" + item.email
      }));
      return data.reduce((acc, next) => acc + next.cost, 0);
    }
    
    async function buildItem(item) {
      const totalCost = await getTotalCost(item);
      let html = `<li class="dd-item" data-id="${item.id}" data-email="${item.email}" data-title="${item.corporateTitle}" data-name="${item.firstName} ${item.lastName}" id="${item.id}">`;
      if (item.children && item.children.length > 0) {
        html += '<ol class="dd-list">';
        for (const childItem of item.children) {
          html += await buildItem(childItem);
        }
        html += "</ol>";
      }
      html += "</li>";
      return html;
    }
    
    function process(item) {
        function getTotalCost(item) {
            var data = jQueryGetJSON(nsynjsCtx, "/retrieveData.do?item=" + item.email).data;
            var totalCost = 0;
            for (var i = 0; i < data.length; i++) {
                totalCost += parseFloat(data[i].cost);
            }
            return totalCost;
        };
    
        function buildItem(item) {
            const totalCost = getTotalCost(item);
            var html = "<li class='dd-item' data-id='" + item.id + "' data-email='" + item.email + "' data-title='" + item.corporateTitle + "' data-name='" + item.firstName + " " + item.lastName + "' id='" + item.id + "'>";
    
            if (item.children && item.children.length > 0) {
                html += '<ol class="dd-list">';
                for (var i=0; i<item.children.length; i++)
                    html += buildItem(item.children[i]);
                html += "</ol>";
            }
            html += "</li>";
            return html;
        };
    
        return buildItem(item);
    };
    
    nsynjs.run(process,{},item,function (itemHTML) {
        console.log("all done",itemHTML);
    });