2017-07-17 5 views
1

ich versuche die folgende Herausforderung lösen, wo ich triggerActions eine Funktion zu schreiben, die einen Rückruf in die processAction gibt, und erzeugt die Ausgabe:Javascript Coding Herausforderung mit setTimeout/Asynchronous Output

"Process Action 1" 
"Process Action 2" 
... 
"Process Action n" 

Hier wird die zur Verfügung gestellt wird Funktion:

function processAction(i, callback) { 
    setTimeout(function() { 
    callback("Processed Action " + i); 
    }, Math.random()*1000); 
} 

Funktion zum Code:

function triggerActions(count) { 

} 

Beachten Sie, dass der Code für processAction nicht geändert werden kann. Ich dachte daran, ein Versprechen zu verwenden, aber ich bin mir nicht sicher, wie. Ich glaube, das setTimeout ist eigentlich synchron, so dass ich nicht weiß, ob async/await funktionieren würde.

Mein Versuch:

triggerActions = count => { 
    let promises = []; 
    for(let i=1; i<=count; i++) { 
    promises.push(new Promise((resolve, reject) => processAction(i, str => resolve(str)))); 
    } 
    let results = [] 
    promises.forEach(promise => Promise.resolve(promise).then(async res => results.push(await res))); 
    return results; 
} 
+2

setTimeout ist eigentlich ** a ** synchron - hast du versucht ** irgendein ** Code, ro willst du jemanden die Herausforderung insgesamt für dich lösen? –

+0

[Promisify] (https://StackOverflow.com/q/22519784/1048572) 'processAction', dann' async' /'await' funktioniert. – Bergi

+0

@JaromandaX Ich habe gerade meinen Post mit meinem Code bearbeitet. – fafafariba

Antwort

1

I der Art, wie kurz und bündig:

var n = 5 
var stop = 1 

triggerActions = function(text) { 
    if (text) console.log(text) 
    if (stop <= n){ 
     processAction(stop++, triggerActions) 
    } 
} 
triggerActions() 

PS

Es kam mir der Gedanke, dass vielleicht Sie sind nur zu schaffen, erlaubt eine Funktion, die die stop Variablendeklaration außerhalb der Funktion bedeutet, ist ein Prob lem. Es macht es ein wenig ausführlicher, aber man kann sie alle in der Funktion wie folgt wickeln:

function triggerActions(stop) { 
    var rFn = (text) => { 
     if (text) console.log(text) 
     if (stop <= n){ 
      processAction(stop++, rFn) 
     } 
    } 
    rFn() 
} 
triggerActions(1) 
1

Dort gehen Sie:

// Your unaltered function 
 
function processAction(i, callback) { 
 
    setTimeout(function() { 
 
    callback("Processed Action " + i); 
 
    }, Math.random()*1000); 
 
} 
 

 
// The function you want to implement 
 
function triggerActions(count) { 
 
    var triggerAction = function (i) { // Local function to process the given action number: 
 
    if (i <= count) {     // More actions to execute? 
 
     processAction(i, function (text) {// Process current action number and pass a callback in parameter 
 
     console.log(text);    // Write the result of processAction    
 
     triggerAction(i + 1);   // Trigger the next action 
 
     });        // 
 
    }         // 
 
    }          
 
    triggerAction(1);      // First things first: start at action one 
 
} 
 

 
// Call the function 
 
triggerActions(10);

+0

Ich würde empfehlen, die Bedingung direkt vor dem 'i ++' anstatt im Callback zu setzen, so dass Ihr Code nicht fehlschlägt, wenn 'count' gleich null ist. – Bergi

+0

@Bergi Danke, dass Sie Recht haben. Ich habe den Code aktualisiert, und ich habe ihn auch durch die Arbeit mit dem 1-basierten Index verbessert. –

0

das ursprüngliche Plakat Instinkt zu verwenden Versprechen war richtig.

Die beiden obigen Lösungen funktionieren möglicherweise, aber da jeder Aufruf von triggerActions() warten muss, bis die Verzögerung abläuft, bevor der nächste Aufruf ausgeführt werden kann, ist dies sehr langsam.

Vielleicht ist es das, was Sie wollen, aber hier ist eine optimierte Lösung verspricht und Promise.all mit():

const processAction = (i, callback) => { 
    setTimeout(function() { 
    callback("Processed Action " + i); 
    }, Math.random()*1000); 
} 

const triggerActions = (n) => { 
    const promises = []; 
    const generatePromise = (i) => { 
    return new Promise((resolve, reject) => { 
     processAction(i, resolve); 
    }); 
    } 
    for (let i = 1; i <= n; i += 1) { 
    promises.push(generatePromise(i)); 
    } 
    Promise.all(promises) 
    .then((strings) => strings.forEach((string) => console.log(string))); 
} 

triggerActions(10); 

die Leistungsunterschiede zu vergleichen, versuchen, die beiden Ansätze nebeneinander laufen.