2017-10-23 4 views
1

Ich versuche derzeit, ein Array von Paaren mit asynchronen Aufrufen in Javascript zu generieren, aber ich kann nicht scheinen, es in der richtigen Reihenfolge zu bekommen.Generieren von Dataset mit Versprechen

generateDataPoints: function (iterable, source, arg) { 
    let pairs = [] 
    let prevTime = 0 
    for (let index in iterable) { 
    let event = iterable[index] 
    getTime(event.valueOf()).then(function (time) { 
     query(source[arg], event.valueOf()).then(function(val) { 
     if (time !== prevTime) { 
      prevTime = time 
      pairs.push([time, val]) 
      console.log(pairs) // This works as expected but only happens after the program returns 
     } else { 
      Promise.resolve() 
     } 
     }) 
    }) 
    } 
    return Promise.resolve(pairs) 
} 

Das Problem ist, dass der Befehl "pairs.push .." passiert, nachdem ich zurückkomme. Ich kann nicht herausfinden, was genau falsch läuft und wie ich diesen Prozess synchronisieren kann. Jede Hilfe wird geschätzt.

+0

so ... äh, Sie sicherlich ein Versprechen in den Code eingeführt, aber nichts, was man mit ihm tat in einem Versprechen führen würde, dass das nicht zurück auflösen, bis die Arbeit erledigt ist. –

+0

@KevinB Hm, ich habe versucht, die for-Schleife in einem neuen Versprechen zu wickeln, während "Entschlossenheit (Paare)" zurückgegeben wird. Das hat auch nicht funktioniert – WhosSu

+0

Sie suchen nach 'Promise.all'. Erstellen Sie mit der Schleife ein Array von Versprechen, eines für jedes einzelne Ergebnis. – Bergi

Antwort

0

Sie mischen synchronen Code (wie die for-Schleife) mit asynchronem Code. Probieren Sie etwas wie folgt aus:

function generateDataPoints(iterable, source, arg) { 
    let prevTime = 0 
    [...iterable].reduce((promiseChain, event) => { 
    let pairs; 
    return promiseChain 
     .then(p => { 
     pairs = p; 
     return Promise.all([ 
      getTime(event.valueOf()), 
      query(source[arg], event.valueOf()) 
     ]) 
     }) 
     .then(([time, val]) => { 
     if (time !== prevTime) { 
      prevTime = time 
      return pairs.concat([[time, val]]); 
     } else { 
      return pairs; 
     } 
     }); 
    }) 
    }, Promise.resolve([])); 
} 

Dies reduziert iterable in eine sequentielle Versprechen Kette, die schließlich alle Paare enthalten.

generateDataPoints: async function (iterable, source, arg) { 
    let pairs = [] 
    let prevTime = 0 
    for (let index in iterable) { 
    let event = iterable[index] 
    const [time, val] = await Promise.all([ 
     getTime(event.valueOf()), 
     query(source[arg], event.valueOf()) 
    ]); 
    if (time !== prevTime) { 
     prevTime = time 
     pairs.push([time, val]) 
    } 
    } 
    return pairs; 
} 

bearbeiten:

bei näherem Hinsehen, ist es nicht

Wenn Ihre Umgebung es zulässt, können Sie auch Ihre Funktion mit wenigen Änderungen an einer async Funktion konvertieren Sieht so aus, als müsstest du diese Versprechen sequenzieren. Sie können in der Lage sein, sie parallel laufen zu lassen, statt:

function generateDataPoints(iterable, source, arg) { 
    Promise.all(
    [...iterable].map(event => Promise.all([ 
     getTime(event.valueOf()), 
     query(source[arg], event.valueOf()) 
    ]) 
).then(pairs => { 
    let prevTime = 0 
    return pairs.filter(([time, val]) => { 
     if (time !== prevTime) { 
     prevTime = time; 
     return true; 
     } else { 
     return false; 
     } 
    }); 
    }); 
} 
+0

Sie verwenden Bluebird auch entsprechend Ihren Tags. Das bedeutet, dass Sie Goodies wie 'Promise.map' haben, die die Dinge noch einfacher machen. – Jacob

+0

Also habe ich die dritte Sache, die du geschrieben hast, implementiert und hier ist das Problem. Ich habe generatedDataPoints an anderer Stelle aufgerufen, lasst uns die Funktion x aufrufen. X ruft die Liste der Paare nach dem Mapping ab, der Filterprozess hat jedoch noch nicht begonnen. Warum ist das? – WhosSu

+0

So sieht es derzeit aus https://pastebin.com/shukspGj – WhosSu

Verwandte Themen