Um einen Stapel unabhängiger Ressourcen zu erhalten, kann const ids = [1001, 1002, 1003, 1004, 1005]; const urlPrefix = "http://opensearch.example.com/api/apps"; // Die Fetch-Funktion sendet eine HTTP-Anfrage und gibt ein Promise zurück const appPromises = ids.map(id => `${urlPrefix}/${id}`).map(fetch); Versprechen.alle(App-Versprechen) // Akkumulieren durch reduce.then(apps => apps.reduce((initial, current) => initial + current.pv, 0)) .catch((Fehler) => console.log(Fehler)); Der obige Code kann normal ausgeführt werden, wenn nicht viele Anwendungen vorhanden sind. Wenn die Anzahl der Anwendungen Zehntausende erreicht, führt Ihr „Stresstest“ bei Systemen, die gleichzeitige Anforderungen nicht sehr gut unterstützen, dazu, dass der Server des Drittanbieters abstürzt und vorübergehend nicht in der Lage ist, auf Anforderungen zu reagieren: <html> <head><title>502 Bad Gateway</title></head> <body bgcolor="weiß"> <center><h1>502 Ungültiges Gateway</h1></center> <hr><center>nginx/1.10.1</center> </body> </html> Wie kann man das Problem lösen? Eine naheliegende Idee ist, dass, da so viele gleichzeitige Anfragen nicht unterstützt werden, es in mehrere große Blöcke aufgeteilt werden kann, von denen jeder ein Die Schwierigkeit liegt in der seriellen Ausführung von Promise. Promise bietet nur parallele ( // task1, task2, task3 sind drei Factory-Funktionen, die Promise zurückgeben und unsere asynchrone Anfrage simulieren const task1 = () => new Promise((resolve) => { setzeTimeout(() => { Entschlossenheit (1); console.log('task1 ausgeführt'); }, 1000); }); const task2 = () => neues Versprechen((auflösen) => { setzeTimeout(() => { Entschlossenheit (2); console.log('Task2 ausgeführt'); }, 1000); }); const task3 = () => neues Versprechen((auflösen) => { setzeTimeout(() => { Entschlossenheit (3); console.log('Task3 ausgeführt'); }, 1000); }); // Aggregationsergebnisse let result = 0; const resultPromise = [Aufgabe1, Aufgabe2, Aufgabe3].reduce((aktuell, nächste) => aktuell.dann((Zahl) => { console.log('aufgelöst mit Nummer', Nummer); // Das Versprechen von Task2, Task3 wird hier aufgelöst Ergebnis += Zahl; nächstes zurückgeben(); }), Promise.resolve(0)) // Anfangswert aggregieren.then(function(last) { console.log('Das letzte mit Nummer eingelöste Versprechen', last); // Das Versprechen von task3 wird hier eingelöst Ergebnis += letztes; console.log('alle mit Ergebnis ausgeführt', Ergebnis); returniere Promise.resolve(Ergebnis); }); Das laufende Ergebnis ist in Abbildung 1 dargestellt: Codeanalyse: Der gewünschte Effekt ist eigentlich Das Problem wurde gelöst. Schauen wir uns den endgültigen Code an: /** * HTTP-Anfrage simulieren * @param {String} url * @return {Versprechen} */ Funktion fetch(url) { console.log(`${url} abrufen`); returniere neues Promise((auflösen) => { setTimeout(() => auflösen({ pv: Nummer(url.match(/\d+$/)) }), 2000); }); } const urlPrefix = "http://opensearch.example.com/api/apps"; konstanter Aggregator = { /** * Eingabemethode, starten Sie die geplante Aufgabe * * @return {Versprechen} */ Start() { gib this.fetchAppIds() zurück .then(ids => diese.fetchAppsSerially(ids, 2)) .then(apps => diese.sumPv(apps)) .catch(Fehler => Konsole.Fehler(Fehler)); }, /** * Alle Anwendungs-IDs abrufen * * @Privat * * @return {Versprechen} */ fetchAppIds() { gibt Promise.resolve([1001, 1002, 1003, 1004, 1005]) zurück; }, VersprechenFactory(IDs) { return () => Promise.all(ids.map(id => `${urlPrefix}/${id}`).map(fetch)); }, /** * Details zu allen Apps abrufen * * Eine gleichzeitige Anforderung von `gleichzeitigen` Anwendungen wird als Chunk bezeichnet. * Der nächste Block wird fortgesetzt, nachdem der vorherige Block gleichzeitig abgeschlossen wurde, bis alle Anwendungen ihn erhalten haben* * @Privat * * @param {[Anzahl]} IDs * @param {Number} concurrency Die Anzahl gleichzeitiger Anfragen zu einem Zeitpunkt* @return {[Object]} Informationen zu allen Anwendungen*/ fetchAppsSerially(ids, Parallelität = 100) { // Chunking let chunkOfIds = ids.splice(0, Parallelität); const Aufgaben = []; während (chunkOfIds.length !== 0) { Aufgaben.push(diese.promiseFactory(chunkOfIds)); chunkOfIds = ids.splice(0, Parallelität); } // In Blockreihenfolge ausführen const result = []; returniere Aufgaben.Reduce((aktuell, weiter) => aktuell.dann((chunkOfApps) => { console.info('Block von', chunkOfApps.length, 'Parallelitätsanforderungen wurden mit folgendem Ergebnis abgeschlossen:', chunkOfApps, '\n\n'); result.push(...chunkOfApps); // Array reduzieren return next(); }), Versprechen.lösen([])) .then((lastchunkOfApps) => { console.info('Chunk of', lastchunkOfApps.length, 'Parallelitätsanforderungen wurden mit folgendem Ergebnis abgeschlossen:', lastchunkOfApps, '\n\n'); result.push(...lastchunkOfApps); // Nochmals abflachen console.info('Alle Chunks wurden mit Ergebnis ausgeführt', result); Ergebnis zurückgeben; }); }, /** * Gesamt-PV aller Anwendungen * * @Privat * * @param {[]} Apps * @return {[Typ]} [Beschreibung] */ SummePv(Apps) { const initial = { pv: 0 }; returniere apps.reduce((Akkumulator, App) => ({ pv: Akkumulator.pv + App.pv }), initial); } }; // Starten Sie die Ausführung von aggregator.start().then(console.log); Das laufende Ergebnis ist in Abbildung 2 dargestellt: Abstraktion und WiederverwendungDas Ziel wurde erreicht. Da es universell ist, werden wir beginnen, es in ein Muster zur Wiederverwendung zu abstrahieren. SeriellSimulieren Sie zuerst eine HTTP-Get-Anfrage. /** * verspottetes http get. * @param {string} URL * @returns {{ url: Zeichenfolge; Verzögerung: Zahl; }} */ Funktion httpGet(URL) { const Verzögerung = Math.random() * 1000; Konsole.info('GET', URL); returniere neues Promise((auflösen) => { setzeTimeout(() => { lösen({ URL (URL = URL = URL), Verzögerung, um: Date.now() }) }, Verzögerung); }) } Führen Sie einen Batch von Anfragen seriell aus. const ids = [1, 2, 3, 4, 5, 6, 7]; // Batch-Anforderungsfunktion. Beachten Sie, dass die durch Verzögerung ausgeführte „Funktion“ korrekt ist. Andernfalls wird die Anforderung sofort gesendet und der serielle Zweck wird nicht erreicht. const httpGetters = ids.map (id => () => httpGet(`https://jsonplaceholder.typicode.com/posts/${id}`) ); // Serielle Ausführung const tasks = await httpGetters.reduce((acc, cur) => { gibt acc.then(cur) zurück; // Kurzform, entspricht // return acc.then(() => cur()); }, Versprechen.auflösen()); Aufgaben.dann(() => { console.log('fertig'); }); Achten Sie auf die Konsolenausgabe, folgendes sollte seriell ausgegeben werden: Holen Sie sich https://jsonplaceholder.typicode.com/posts/1 Holen Sie sich https://jsonplaceholder.typicode.com/posts/2 Holen Sie sich https://jsonplaceholder.typicode.com/posts/3 Holen Sie sich https://jsonplaceholder.typicode.com/posts/4 Holen Sie sich https://jsonplaceholder.typicode.com/posts/5 Holen Sie sich https://jsonplaceholder.typicode.com/posts/6 Holen Sie sich https://jsonplaceholder.typicode.com/posts/7 Segment seriell, Segment parallelHier kommt der Punkt. Die Implementierung des Anforderungsplaners in diesem Artikel /** * Planen Sie Versprechen. * @param {Array<(...arg: any[]) => Promise<any>>} Fabriken * @param {number} Parallelität */ Funktion schedulePromises(Fabriken, Parallelität) { /** * Stück * @param {any[]} arr * @param {number} Größe * @returns {Array<any[]>} */ const chunk = (arr, Größe = 1) => { returniere arr.reduce((acc, cur, idx) => { const modulo = idx % Größe; wenn (modulo === 0) { acc[acc.Länge] = [aktuell]; } anders { acc[acc.Länge - 1].push(aktuell); } Rückgabe gem. }, []) }; const chunks = chunk(Fabriken, Parallelität); lass resps = []; Rückgabewerte für chunks.reduce( (account, aktuell) => { Rückgabe-Ac .then(() => { konsole.log('---'); Fügt Promise.all zurück (aktuell.map(f => f())); }) .then((Zwischenantworten) => { resps.push(...Zwischenantworten); Rückgabeantworten; }) }, Versprechen.lösen() ); } Führen Sie zum Testen den Scheduler aus: // Segmentiert seriell, segmentiert parallel schedulePromises(httpGetters, 3).then((resps) => { Konsole.log('resps:', resps); }); Konsolenausgabe: --- Holen Sie sich https://jsonplaceholder.typicode.com/posts/1 Holen Sie sich https://jsonplaceholder.typicode.com/posts/2 Holen Sie sich https://jsonplaceholder.typicode.com/posts/3 --- Holen Sie sich https://jsonplaceholder.typicode.com/posts/4 Holen Sie sich https://jsonplaceholder.typicode.com/posts/5 Holen Sie sich https://jsonplaceholder.typicode.com/posts/6 --- Holen Sie sich https://jsonplaceholder.typicode.com/posts/7 resps: [ { "URL": "https://jsonplaceholder.typicode.com/posts/1", "Verzögerung": 733.010980640727, "um": 1615131322163 }, { "URL": "https://jsonplaceholder.typicode.com/posts/2", "Verzögerung": 594.5056229848931, "um": 1615131322024 }, { "URL": "https://jsonplaceholder.typicode.com/posts/3", "Verzögerung": 738.8230109146299, "um": 1615131322168 }, { "URL": "https://jsonplaceholder.typicode.com/posts/4", "Verzögerung": 525.4604386109747, "um": 1615131322698 }, { "URL": "https://jsonplaceholder.typicode.com/posts/5", "Verzögerung": 29.086379722201183, "um": 1615131322201 }, { "URL": "https://jsonplaceholder.typicode.com/posts/6", "Verzögerung": 592.2345027398272, "um": 1615131322765 }, { "URL": "https://jsonplaceholder.typicode.com/posts/7", "Verzögerung": 513.0684467560949, "um": 1615131323284 } ] Zusammenfassen
Oben sind die Details der JS-Implementierung des Anforderungsplaners aufgeführt. Weitere Informationen zum JS-Anforderungsplaner finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM! Das könnte Sie auch interessieren:
|
>>: So aktivieren oder deaktivieren Sie Linux-Dienste mit den Befehlen chkconfig und systemctl
Im Lernprogramm zum Docker-System haben wir geler...
Vorwort Während des Schreibens des Codes werden w...
Hintergrund In einer Liste wie der folgenden erfo...
Normalerweise färben wir als Webmaster während de...
a href="#"> Nach dem Klicken auf den ...
Vorwort In MySQL ist die Abfrage mehrerer Tabelle...
HTML-Formulare werden verwendet, um verschiedene ...
[LeetCode] 176. Zweithöchstes Gehalt Schreiben Si...
Finden Sie das Problem Ich habe vor Kurzem Django...
Inhaltsverzeichnis 1. Ursache 2. Geräteinformatio...
In diesem Artikel finden Sie das grafische Tutori...
Installieren Sie MySQL 8.0 docker run -p 63306:33...
Meine Umgebung: 3 centos7.5 1804 Meister 192.168....
1. Einleitung Responsive Webdesign ermöglicht die...
Umfeld: 1. Windows Server 2016 Datacenter 64-Bit ...