2016-06-01 20 views
2

Update: Ich weiß jetzt, dass Drossel überschüssige Funktionsaufrufe fallen lassen wird, so ist es nicht das richtige Werkzeug. Ich würde immer noch eine idiomatische Art und Weise mögen, alle Gegenstände in einer Schlange zu bearbeiten, ohne zu schnell zu gehen oder irgendwelche Gegenstände fallen zu lassen.Rate Limit Funktionsaufrufe in Typescript


Ich schreibe eine Knoten-App, die eine API mit einem Ratenlimit trifft. Ich kann Anrufe viel schneller erstellen, als ich ihnen senden darf. Ich möchte eine Warteschlange von Anrufen konsumieren, aber ohne zu schnell zu gehen oder irgendwelche von ihnen fallen zu lassen. Ich machte einen kleinen Typescript Test meine Probleme zu veranschaulichen:

import * as _ from "lodash"; 

let start = new Date().getTime(); 

function doLog(s: string) { 
    let elapsed = new Date().getTime() - start; 
    console.log(`${s} ${elapsed}`); 
} 

let array = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']; 
let throttled = _.throttle(doLog, 100); 
array.forEach(s => throttled(s)); 

Ich erwartete Ausgabe zu sehen, etwa wie:

a 2 
b 101 
c 203 
d 302 
e 405 
f 502 
g 603 
h 706 
i 804 
j 902 

Aber stattdessen sehe ich:

a 2 
j 101 

einige merkwürdige Beobachtungen I‘ ve made:

  • Bei 100ms Drossel, die si ze des Arrays scheint irrelevant: Ich werde das erste und letzte Element im Array drucken, ob es 2 Elemente oder 20 hat.
  • Bei 1ms Drossel, drucke ich 3-6 Elemente von der Vorderseite des Arrays, und die letzte Element
+0

Ja, das ist nicht, wofür gedrosselt ist. Siehe [die Dokumentation] (https://lodash.com/docs#throttle). Du kannst deine eigene Klasse schreiben, die das gewünschte Verhalten hat ... Ich denke nicht, dass es etwas in Lodash gibt, das damit umgehen kann. –

+0

habe ich schon getan. Ich habe auch den Artikel von David Corbacho gelesen, der in den Dokumenten verlinkt ist. Die Dokumentation sagt "Die gedrosselte Funktion kommt mit einer Cancel-Methode zum Abbrechen verzögerter Func-Aufrufe und einer Flush-Methode, um sie sofort aufzurufen." Dieser Ausdruck "verzögerte Func Invocations" klingt sicher so, als würde er mich anrufen. Aber es klingt, als würde ich mich irren, was in Ordnung ist. Gibt es eine andere Funktion/Dienstprogramm, die ich verwenden sollte? –

Antwort

2

Wenn Sie nicht kümmern uns um doLog() sicher ist „fertig“, bevor der nächste Aufruf ein, können Sie setTimeout

let array = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']; 
array.forEach((s, i) => setTimeout(doLog, i*100, s)); 

Adam verwenden nur eine gute Erklärung gibt, warum throttle in diesem cas ist nicht gut e.

+0

Ahh, so einfach! Ich habe versucht, SetTimeout, aber nicht in Betracht ziehen, dynamisch die Verzögerung inkrementieren. –

2

Wenn eine gedrosselte Funktion mehr als einmal während der Wartezeit aufgerufen wird, werden nachfolgende Aufrufe ignoriert. Wenn Sie jedes Element in einem Array verarbeiten müssen, ist throttle() wahrscheinlich nicht das, was Sie wollen. Es ist besser geeignet, um beispielsweise übermäßige Aktualisierungen in der Benutzeroberfläche zu verhindern.

Der Grund, warum Sie immer a und j in Ihrer Ausgabe sehen, liegt an Vorder- und Hinterkanten. Das gesamte Array wurde in weniger als 100 ms verarbeitet. Da jedoch der Standardwert für "Vorlauf" und "Nachlauf" auf "Wahr" gesetzt ist, werden beide Aufrufe angezeigt (der erste und der letzte Aufruf der gedrosselten Funktion).

+0

Danke für die Klärung der Vorder-/Hinterkanten; das hilft, den Output sinnvoll zu machen. Gibt es eine idiomatische Lösung (oder Bibliothek) für die Verarbeitung jedes Elements in einem Array mit einer bestimmten Rate? –

+0

Ich bin mir sicher, dass es da ist. Warum möchten Sie die Array-Verarbeitung aus reiner Neugier begrenzen? –

+0

Ich rufe viele Male eine API an, und diese API wird mich ablehnen, wenn ich zu schnell gehe. Ich bin weit unter der Tagesrate, aber ich kann leicht die Rate pro Sekunde hochschnellen. –

0

Wenn Sie bereit sein würde RxJS zu verwenden, würde diese Antwort können Sie dies erreichen ziemlich idiomatisch:

https://stackoverflow.com/a/31855054/553003

+0

Keine schlechte Idee! ... erfüllt die Anforderungen besser als andere Lösungen –