2017-07-17 2 views
1

Je suis en train de résoudre le défi suivant où je dois écrire une fonction triggerActions qui passe un rappel dans le processAction et produit la sortie:codage JavaScript défi avec setTimeout/Asynchronous Sortie

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

Voici la condition fonction:

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

fonction de code:

function triggerActions(count) { 

} 

Notez que le code processAction ne peut pas être modifié. Je pensais utiliser une promesse mais je ne sais pas comment. Je crois que le setTimeout est réellement synchrone donc je ne sais pas si async/await fonctionnerait.

Ma tentative:

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 est en réalité ** a ** synchrone - avez-vous essayé ** tout ** code, vous voulez quelqu'un pour résoudre le défi au total pour vous? –

+0

[promisify] (https://stackoverflow.com/q/22519784/1048572) 'processAction', puis' async' /'await' fonctionnera. – Bergi

+0

@JaromandaX Je viens d'éditer mon post avec mon code. – fafafariba

Répondre

1

Je aime bien court et doux:

var n = 5 
var stop = 1 

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

PS

Il me est apparu que peut-être vous êtes que autorisés à fournir une fonction qui signifie que la déclaration de variable stop en dehors de la fonction est un prob lem. Il fait un peu plus bavard, mais vous pouvez envelopper tout l'intérieur de la fonction comme ceci:

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

Là vous allez:

// 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

Je recommande de mettre la condition juste devant le 'i ++' au lieu de dans le rappel, de sorte que votre code n'échoue pas lorsque 'count' est zéro. – Bergi

+0

@Bergi merci d'avoir raison. J'ai mis à jour le code et je l'ai également fait effacer en travaillant avec l'index basé sur 1. –

0

instinct de l'affiche originale d'utiliser les promesses étaient correctes.

Les deux solutions ci-dessus peuvent fonctionner mais comme chaque appel à triggerActions() doit attendre que le délai se soit écoulé avant que l'appel suivant puisse être effectué, ceci est considérablement lent.

Peut-être que c'est ce que vous voulez, mais voici une solution optimisée en utilisant des promesses et Promise.all():

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

Pour comparer les différences de performance, essayez d'exécuter le côté deux approches côte à côte.