2017-06-06 4 views
0

Ich bin nicht sicher, wie diese Liste (die eine Zeichenfolge ist) erstellt und dann als eine vollständige Zeichenfolge zurückgegeben wird. Ich habe an meiner letzten Ausgabe gearbeitet, aber ich denke, dass diese mich wirklich nervt. buildItem() sollte durch item durchlaufen und dann rekursiv eine Liste erstellen, während die totalCost von einem anderen Callback abgerufen wird. Ich weiß, es asynchron arbeitet ...Wie rekursiv eine Liste mit einem Rückruf erstellen und durch die Kinder durchlaufen?

buildItem(data, function(html){ 
    $('#nestable ol').append(html); 
}); 

anhängen soll die ‚endgültige‘ HTML-String, der vor einer angehängten im gesamten Datei erstellt wird.

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

Ich weiß, dass

buildItem(item, function(subHtml){ 
    html += subHtml; 
}) 

sollte nicht funktionieren, da Javascript asynchron ist. Ich bin mir nicht sicher, wie ich von einer rekursiven Funktion zurückkehren soll. Wenn ich etwas zu tun, waren wie

buildItem(item, function(subHtml){ 
    callback(subHtml); 
}) 

werden Sie doppelte Werte erhalten, weil Sie den Startwert haben werden und es ist Kinder, aber da du auch bist nannte es Sie werden die Kinder außerhalb der zurück Startwert. So wird es aussehen

1 
    a 
    b 
    c 
    d 
    e 
a 
b 
c 
d 
e 

Also, was ist der beste Weg, um eine Lösung zu nähern? Ich dachte daran, eine andere Funktion, hypothetisch eine buildChild (sub), die HTML zurückgegeben, aber das gleiche Problem mit asynchrone wird kommen, wo die Rückkehr wird undefiniert. Ich habe einige der Threads gelesen, in denen Sie asynchrone Werte mit Rückrufen behandeln können, aber ich bin mir nicht sicher, wie es mit der Rekursion hier gemacht wird.

getTotalCost ist eine weitere Callback-Funktion, die nicht viel bedeuten sollte, ich habe die Zeile aus Versehen entfernt, aber ich brauche nur die totalCost aus einer Datenbank.

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

Antwort

0

Sie können diese Vereinfachung mit promises und async functions:

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

Leider sind Asynchron-Funktionen nicht von allen Browsern noch unterstützt, so dass Sie Babel verwenden, haben Sie Ihren Code transpile.

Ich habe auch einige neue ES6-Funktionen hinzugefügt: arrow functions, const und template literals.

+0

Ich könnte ich könnte, aber ich arbeite mit IE11 und der Code, der transpiled bekommt sieht nicht einfach zu pflegen. Ich hatte gehofft, dass es eine Lösung geben würde, um auf dem aufzubauen, was ich bereits habe. – CHom

+0

@CHom Was meinst du? Sie verwalten nicht transpilierten Code - es ist nur für den Browser. –

+0

Ich entwickle, um auf einer großen Website verwendet zu werden, und als einer der Entwickler in diesem Projekt glaube ich nicht, dass ich eine so große Änderung vornehmen möchte, wie Code für eine bestimmte Sektion gemacht wird. Ich würde es gerne benutzen, wenn ich nicht bei diesem Projekt wäre. – CHom

0

Sie können langsame Ajax-Anfragen mit Logik und Rekursion mischen, wenn Sie Ihren Code über den synchronen Executor nsynjs ausführen.

Schritt 1. Ihre Logik schreiben, als ob es synchron war, und in Funktion setzen:

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

Schritt 2: es über nsynjs laufen:

nsynjs.run(process,{},item,function (itemHTML) { 
    console.log("all done",itemHTML); 
}); 

Bitte weitere Beispiele siehe hier: https://github.com/amaksr/nsynjs/tree/master/examples

Verwandte Themen