Ich habe ein Skript, um ~ 1000 Webseiten zu scrappen. Ich verwende Promise.all sie zusammen zu schießen, und es gibt, wenn alle Seiten fertig sind:Ich kann die Versprechungen wegen zu wenig Arbeitsspeicher nicht abschließen
Promise.all(urls.map(url => scrap(url)))
.then(results => console.log('all done!', results));
Das ist süß und richtig, mit einer Ausnahme - Maschine aus dem Speicher wegen der gleichzeitigen geht Anfragen. Ich benutze jsdom
für die Verschrottung, es nimmt schnell ein paar GB Mem, was verständlich ist, wenn man bedenkt, dass es Hunderte von window
instanziiert.
Ich habe eine Idee zu beheben, aber ich mag es nicht. Das heißt, ändern Steuerfluss nicht Promise.all zu verwenden, aber Kette meine Versprechen:
let results = {};
urls.reduce((prev, cur) =>
prev
.then(() => scrap(cur))
.then(result => results[cur] = result)
//^not so nice.
, Promise.resolve())
.then(() => console.log('all done!', results));
Dies ist nicht so gut wie Promise.all ... nicht performant wie es gekettet ist, und Rückgabewerte gespeichert werden müssen für die spätere Verarbeitung.
Irgendwelche Vorschläge? Soll ich den Kontrollfluss verbessern oder sollte ich die Speicherauslastung in scrap() verbessern, oder gibt es eine Möglichkeit, den Knoten auf die Speicherzuweisung zu beschränken?
Ich verstehe nicht, was Sie meinen „Nicht performant wie es * gekettet ist“ – Bergi
Btw, braucht es '.then (() => Schrott zu sein (cur)) ' – Bergi
@Bergi vielleicht liege ich hier falsch. Ich denke, der langsame Teil ist eine Anfrage an eine URL. In der verketteten Version können Sie die nächste Anfrage nur auslösen, nachdem wir alle Schrottarbeiten an der vorherigen URL durchgeführt haben. In der Promise.all-Version können sie alle starten (sendende http-Anfrage ist natürlich async), und behandelt werden, wenn sie zurück sind – Boyang