2017-01-06 1 views
4

Ich habe derzeit einen Anmeldeprozess und bei jedem weiteren Klick wird eine Promise.all() erstellt, die viele HTTP-Anfragen aufruft. Wenn der Client sehr schnell durchgeht (die nächsten Tasten werden sehr schnell gedrückt), baut sich die HTTP-Anfrage auf und es macht meine App durcheinander.Wie storniere ich eine Promise.all() in Angular 2?

Gibt es eine Möglichkeit, eine Promise.all() abzubrechen, so dass, wenn sie weiter klicken und die vorherige Promise.all() noch läuft, kann ich es einfach abbrechen?

+3

Versprechen sind nicht stornierbar. Es gab eine Spezifikation in der Arbeit, um sie so zu machen, aber die Arbeit daran wurde gestoppt. – toskv

+1

@toskv Also, Versprechen sind nicht kündbar, aber die Spezifikation, um kündbare Versprechen zu machen, war selbst offensichtlich kündbar. –

+1

@ JeffBowman leider war es sehr stornierbar. :( – toskv

Antwort

4

Sie können darauf warten, dass die Versprechungen zu Ende geführt werden, Sie können sie jedoch nicht abbrechen.

Sie können die nächste Schaltfläche deaktivieren, bis alle fertig sind.

<button [disabled]="completed">Next</button>

0

Unter der Annahme, dass "ein Promise.all cancel()" bedeutet "sicherzustellen, dass die von einem Promise.all zurück Versprechen() nicht seinem Erfolg Pfad folgen" ....

Versprechen sind nicht stornierbar, aber Muster-basierte Lösung (en) sind verfügbar.

Das Konzept hier ist relativ einfach. Im Wesentlichen sind Sie können in jeder Charge von Versprechen ein Versprechen, dass:

  • gelöst werden, wenn die Rohmasse erfolgreich
  • wird bei der Erstellung der nächsten Charge zurückgewiesen werden.

Es ist eine Art Rasse des Guten gegen das Böse.

Der schwierige Teil macht die "Super-Aggregation" transparent für die Ergebnisse.

Hier ist eine Möglichkeit, es zu schreiben - vielleicht nicht die prägnanteste - jemand kann einen besseren Weg finden.

function BatchCanceller() { 
    // Return a function, which accepts an array of promises and returns an aggregated promise. 
    // Use the returned function like $q.all(). 
    var dfrd; 
    return function(promises) { 
     if(dfrd) { 
      dfrd.reject(new Error('cancelled')); // reject previous batch 
     } 
     dfrd = $q.defer(); 
     // Preparation; ensure that `promises`, if all are successful, resolve `dfrd`. 
     $q.all(promises).then(dfrd.resolve); 
     // Now include `dfrd` in a super-aggregation of `promises` 
     return $q.all(promises.concat(dfrd.promise)) // Will the aggregated `promises` resolve before another batch causes `dfrd.reject()`? 
     .then(function(results) { 
      // Yay! the aggregated `promises` won out. 
      return results.splice(0, results.length-1); // remove the unwanted extra result. 
     }); // no need to handle error here 
    }; 
} 

var batchCanceller = new BatchCanceller(); 

var promises = [/* whatever */]; 
batchCanceller(promises).then(function(results) { 
    console.log(results); 
}).catch(function(error) { 
    console.log(error); // message is "cancelled" if another `batchCanceller(promises)` is executed before the previous one resolves. 
}); 

In der Praxis würden Sie wahrscheinlich wählen BatchCanceller() als Angular Werk zum Ausdruck bringen.

0

Ich würde Observablen verwenden, switchMap und debounceTime, so etwas wie

export class MyComponent implements OnInit { 
    actions: Observable<any[]>; 
    private signals = new Subject<string>(); 
    constructor() {} 

    submit(signal: string): void { 
    this.signals.next(signal); 
    } 

    ngOnInit(): void { 
    this.actions = this.signals 
     .debounceTime(300)   
     .distinctUntilChanged() 
     .switchMap(signal => { 
     // make http calls with the signal e.g 
     // return this.service.getAction(signal) 
     }) 
     .catch(error => { 
     // handle error 
     }); 
    } 
} 

die auf https://angular.io/docs/ts/latest/tutorial/toh-pt6.html#!#-_observable-s

Eine nette Sache basiert über switchMap wird jeder im Flug HTTP-Anfragen stornieren, wenn ein anderes Signal kommt durch . Wenn Ihr Server keine abgebrochenen Anfragen bearbeitet, hilft das nicht viel.

+0

Hängt diese Lösung nicht davon ab, dass die hartcodierte '.debounceTime (300)' ein passendes Modell dessen ist, was entlarvt wird? Was, wenn sein '$ q.all()' mehr als 300 ms brauchte, um es abzurechnen? –

+0

Hmm, ich hätte die Frage vielleicht falsch verstanden, ich dachte, die OP wollte die Arbeitsbelastung der App Server verringern, dh das Backend die Frontend eckige App? – shusson

+0

Ich denke, Sie könnten das aus dem ersten Absatz der Frage verstehen, aber nicht die zweite. Lesen Sie noch einmal, ob Sie einverstanden sind. –

Verwandte Themen