2017-10-05 4 views
0

sagen, dass ich ein Array von Objekten haben, die asynchrone Methoden haben:Erstellen asynchrone Wasserfall von Objekten

[ 
    { 
    partOne: function(input) { 
     // Do something async 
    }, 
    partTwo: function(result) { 
     // Do something w/ result of partOne 
    } 
    }, 
    { 
    partOne: function(resultOfPrevious) { 
     // Do something async 
    }, 
    partTwo: function(result) { 
     // Do something w/ result of partOne 
    } 
    }, 
    { 
    partOne: function(resultOfPrevious) { 
     // Do something async 
    }, 
    partTwo: function(result) { 
     // Do something w/ result of partOne 
    } 
    } 
] 

Ich möchte PartOne des ersten Objekts mit meinem Eingang, übergeben Sie das Ergebnis (async) an die PartTwo Rückruf auszuführen Übergeben Sie dann das Ergebnis von partTwo als Eingabe an partOne des nächsten Objekts und so weiter. Das Array kann aus einem oder mehreren Objekten bestehen. Ich frage mich, was das beste Muster ist, um diese Art von Code auszuführen?

Es ist etwas ähnlich wie die Wasserfall-Methode von async.js: https://caolan.github.io/async/docs.html#waterfall, aber ich frage mich, wie ich das ohne eine Bibliothek und möglicherweise mit sauberer Code tun kann?

Nicht sicher, ob async/await hier helfen könnte?

Antwort

2

eine weitere Option ohne jeden Rückruf zu einem Array zu sammeln, mit async/await:

async function processWaterfallObject (data, input) { 
    let result = input 

    for (let entry of data) { 
    result = await entry.partOne(result) 
    result = await entry.partTwo(result) 
    } 

    return result 
} 

Dies setzt voraus, dass die Funktionen in Ihrem data Array entweder async sind oder geben Sie eine Promise zurück.


async/await wird derzeit von every major browser unterstützt und ist in node seit 7.6.0 zur Verfügung.

+0

Sehr schön, sehr sauber. –

0

Objekte Array von in der ursprünglichen Frage gegeben Unter der Annahme, unter einem variablen Wasserfall

let collector = []; 
for (waterfallObj of waterfall) { 
    let tempArr = Object.values(waterfallObj);//get the functions out of the object 
    for (waterfallFunc of tempArr) { 
    collector.push(waterfallFunc); 
    } 
} 
//now you have your functions in order in collector 
function recursiveCallback(i) { 
    if (i>collector.length-1) { 
    return;//if there are no more to call then return 
    } 

    collector[i]().then(function(){ 
    recursiveCallback(i+1); 
    }); 
} 

Wenn Sie die nächste Funktion, etwas zu tun mit dem bisherigen Funktion Wert wollen dann einfach die dann aufgerufen wird dann umsteigen (function (passedValue und verwendet dann diese passedValue im recursiveCallback Anruf innerhalb es

+0

Sie sind nicht 'pop'ping irgendwo von der' collector', so die 'recursiveCallback' Funktion wird nur mit' maximale Call-Stack-Größe überschritten 'zu werfen. –

+0

Warum sollte ich knallen müssen? Ich habe eine Return-Anweisung dort für, wenn alle Sammlerfunktionen verarbeitet worden sind – Shard

+0

Mein schlechter, Sie sind völlig richtig. Ich habe den 'i> ...' Teil übersehen. –

1

Hier ist eine einfache Funktion jeder asynchrone Funktion in einem Stapel aufzurufen

function drain(stack, initialArg) { 
    stack.reduce(function (sectArg, section) { 
    return Object.keys(section).reduce(async function (arg, key) { 
     return await section[key].call(null,arg) 
    }, sectArg) 
    }, initialArg) 
} 

es sicherzustellen, nutzen zu können, dass jede Funktion in Sie gibt einen Wert

var stack = [ 
    { 
    partOne: function(input) { 
     // Do something async 
     console.log('section one partOne', input) 
     return 'section one partOne output' 
    }, 
    partTwo: function(result) { 
     // Do something w/ result of partOne 
     console.log('section one partTwo', result) 
     return 'section one partTwo output' 
    } 
    }, 
    { 
    partOne: function(resultOfPrevious) { 
     // Do something async 
     console.log('section two partOne', resultOfPrevious) 
     return 'section two partOne output' 
    }, 
    partTwo: function(result) { 
     // Do something w/ result of partOne 
     console.log('section two partTwo', result) 
     return 'section two partTwo output' 
    } 
    }, 
    { 
    partOne: function(resultOfPrevious) { 
     // Do something async 
     console.log('section three partOne', resultOfPrevious) 
     return 'section three partOne output' 
    }, 
    partTwo: function(result) { 
     // Do something w/ result of partOne 
     console.log('section three partTwo', result) 
     return 'section three partTwo output' 
    } 
    } 
] 

So stapeln, dass Sie die aufrufen stapeln wie

drain(stack, 'initialArg') 

sehen Sie diese jsfiddle: https://jsfiddle.net/kqj0rror/

+0

Dies berücksichtigt nicht, dass die Funktionen asynchron sind. –

+0

Ich habe editted, um Async-Funktionen unterzubringen – kharhys

+0

Großartig! Ich habe auch bemerkt, dass du 'call'ing' mit 'this' verbunden bist - ich bin mir nicht sicher, ob das eine großartige Idee ist, es könnte zu vielen unerwarteten Fehlern im Code führen. Vielleicht solltest du stattdessen 'null' verwenden? –

Verwandte Themen