2016-12-01 1 views
0

Ich bin neugierig zu wissen, wie kann ich Bluebird Versprechen in meinem vorhandenen Javascript-Code, der viele Callback-basierte Mechanismen nutzt. Hier ist das Szenario:Wie man Bluebird Versprechen auf meine vorhandene Javascript Traversal und rekursive basierte Logik anwenden?

In meiner Web-Anwendung auf Seite Last mit jQuery, ich Seite Hauptmenü Links erhalten und eine TreeModel Struktur von ihnen erzeugen, die ich später verwenden werde ein Brotkrumen auf Seite oben zu zeigen.

Die Funktion, die ich für die Erzeugung dieses TreeModel bin mit folgt:

function _traverseNodeChildren(selector, parentNode, callback1, callback2) { 

    $(parentNode.model.element).find(selector).each(function(idx, elm) { 

     // Create a Tree Node using TreeModel 
     let node = _createTreeNode.apply(this.comp, [elm]); 
     this.parentNode.addChild(node); 

     let hasChildren = $(elm).find("+ul.dropdown-menu").length > 0; 
     if (hasChildren == true) 
      _traverseNodeChildren.apply(this.comp, ["+ul.dropdown-menu > li > a", node, callback1, callback2]); 

     if (node.model.id == "aboutLink") // last node 
     { 
      setTimeout(() => { 
       callback1.apply(this.comp, [callback2]); 
      }, 100); 
     } 
    }.bind({parentNode: parentNode, comp: this})); 
} 

Nach oben Traversal abgeschlossen ist, möchte ich myServerCall Funktion aufrufen, die ein asynchrones Ajax-Anfrage beinhalten wird und es zu Abschluss dieses Asynchron-Anfrage, endlich möchte ich eine dritte Funktion aufrufen myFinalFunc.

Derzeit verwende ich folgenden Code, um diesen Traversal-Code zu machen ausführen:

const TreeModel = require('tree-model'); 
const _treeModel = new TreeModel(); 

let _bcRoot = _treeModel.parse({ 
    id: "0", 
    href: null, 
    text: "", 
    element: $(".main-menu").get(0) 
}); 

_traverseNodeChildren.apply(this, ["> li > a[data-bc-id]", 
      _bcRoot, myServerCall, myFinalFunc]); 

Aber ich mag es drossel Versprechen basierter Ansatz umgesetzt werden, um mehr Kontrolle über sie zu bekommen.

Im Folgenden finden Sie den Code, ich mag es will am Ende sein:

_traverseNodeChildren.apply(this, ["> li > a[data-bc-id]", _bcRoot]) 
    .then(function() { 
     return myServerCall(); 
    }) 
    .then(function() { 
     return myFinalFunc(); 
    }) 
    .catch(function(error) { 

    }); 

Wie kann ich dies mit drossel tun?

+0

Was ist 'callback1', was ist' callback2'? Warum verwenden Sie 'setTimeout' in' _traverseNodeChildren' überhaupt, scheint es nichts Asynchrones zu tun? – Bergi

+0

Warum all diese 'apply' Anrufe? Sind Ihre Zielinstanzen nicht die entsprechenden Methoden? – Bergi

+0

@bergi Dies ist in der Tat eine Art Pseudo-Code. Bezüglich callback1 n callback2 hast du meine ganze Frage gelesen? Dies sind 'myServerCall' und' myFinalFunc'. Und diese beiden Funktionen werden async sein –

Antwort

1

Ich beginne mit dem Rückruf-Code

function traverseNodeChildren(comp, selector, parentNode, callback) { 
    $(parentNode.model.element).find(selector).each(function(_, elm) { 
     // Create a Tree Node using TreeModel 
     let node = createTreeNode(comp, elm); 
     parentNode.addChild(node); 

     let hasChildren = $(elm).find("+ul.dropdown-menu").length > 0; 
     if (hasChildren) 
      _traverseNodeChildren(comp, "+ul.dropdown-menu > li > a", node, callback); 

     if (node.model.id == "aboutLink") 
      setTimeout(function() { 
       callback(comp); 
      }, 100); 
     } 
    }); 
} 

traverseNodeChildren(this, "> li > a[data-bc-id]", _bcRoot, function(comp) { 
    myServerCall.call(comp, myFinalFunc) 
}); 

jedoch vereinfacht, da callback möglicherweise mehrmals aufgerufen wird (wenn es mehrere aboutLinks), können Sie diese Versprechungen nicht wirklich konvertieren. Es sei denn, du möchtest, dass es sich anders verhält.
Wenn es nur einen AboutLink gibt, brauchen Sie die Asynchronität und die Rückrufe überhaupt nicht in Ihrer Traversalfunktion. Just do

function traverseNodeChildren(comp, selector, parentNode) { 
    $(parentNode.model.element).find(selector).each(function(_, elm) { 
     // Create a Tree Node using TreeModel 
     let node = createTreeNode(comp, elm); 
     parentNode.addChild(node); 

     let hasChildren = $(elm).find("+ul.dropdown-menu").length > 0; 
     if (hasChildren) 
      _traverseNodeChildren(comp, "+ul.dropdown-menu > li > a", node); 
    }); 
} 

traverseNodeChildren(this, "> li > a[data-bc-id]", _bcRoot); 
setTimeout(function() { 
    myServerCall(myFinalFunc) 
}, 100); 

, die Sie jetzt leicht umwandeln können, ohne auch nur zu strahlend blauer Himmel zu berühren traverseNodeChildren:

traverseNodeChildren(this, "> li > a[data-bc-id]", _bcRoot); 
Promise.delay(100) 
.then(myServerCall) 
.then(myFinalFunc) 
.catch(function(err) { … }); 

Wenn Sie irgendeine Art von verzögerten Traversal möchten, die auf jedem Knoten wartet, können Sie

verwenden
function traverseNodeChildren(comp, selector, parentNode) { 
    return Promise.mapSeries($(parentNode.model.element).find(selector), function(elm) { 
     // Create a Tree Node using TreeModel 
     let node = createTreeNode(comp, elm); 
     parentNode.addChild(node); 

     let hasChildren = $(elm).find("+ul.dropdown-menu").length > 0; 
     if (hasChildren) 
      return _traverseNodeChildren(comp, "+ul.dropdown-menu > li > a", node); 
     else 
      return Promise.delay(100); 
    }); 
} 

traverseNodeChildren(this, "> li > a[data-bc-id]", _bcRoot) 
.then(myServerCall) 
.then(myFinalFunc) 
.catch(function(err) { … }); 
+0

Es gibt nur ein AboutLink im Hauptmenü der Seite und es wird der letzte Knoten in der Traversierung sein. –

+0

Warum hast du dem Traversal überhaupt einen Rückruf gegeben? Gehen Sie einfach synchron durch das Menü und starten Sie danach das Timeout. – Bergi

+0

Btw, musstest du 'this.comp' wirklich in den Callback übernehmen? – Bergi

Verwandte Themen