Ich habe einen Code, der Daten mit Breeze speichert und den Fortschritt über mehrere Speichervorgänge meldet, der einigermaßen gut funktioniert. Manchmal wird ein Speicher jedoch Timeout, und ich möchte es einmal automatisch versuchen. (Zur Zeit wird dem Benutzer ein Fehler angezeigt und er muss es erneut manuell versuchen) Ich habe Mühe, einen geeigneten Weg zu finden, aber ich bin verwirrt von Versprechungen, also würde ich mich über Hilfe freuen. Hier ist mein Code:
//I'm using Breeze, but because the save takes so long, I
//want to break the changes down into chunks and report progress
//as each chunk is saved....
var surveys = EntityQuery
.from('PropertySurveys')
.using(manager)
.executeLocally();
var promises = [];
var fails = [];
var so = new SaveOptions({ allowConcurrentSaves: false});
var count = 0;
//...so I iterate through the surveys, creating a promise for each survey...
for (var i = 0, len = surveys.length; i < len; i++) {
var query = EntityQuery.from('AnsweredQuestions')
.where('PropertySurveyID', '==', surveys[i].ID)
.expand('ActualAnswers');
var graph = manager.getEntityGraph(query)
var changes = graph.filter(function (entity) {
return !entity.entityAspect.entityState.isUnchanged();
});
if (changes.length > 0) {
promises.push(manager
.saveChanges(changes, so)
.then(function() {
//reporting progress
count++;
logger.info('Uploaded ' + count + ' of ' + promises.length);
},
function() {
//could I retry the fail here?
fails.push(changes);
}
));
}
}
//....then I use $q.all to execute the promises
return $q.all(promises).then(function() {
if (fails.length > 0) {
//could I retry the fails here?
saveFail();
}
else {
saveSuccess();
}
});
bearbeiten zu klären, warum ich dies versucht haben: ich einen http-Abfangjäger, die ein Timeout auf alle HTTP-Anfragen setzt. Wenn eine Anforderung eine Zeitüberschreitung aufweist, wird das Zeitlimit nach oben angepasst. Dem Benutzer wird eine Fehlernachricht angezeigt, in der er ihnen mit einer längeren Wartezeit erneut versuchen kann, falls sie dies wünschen.
Das Senden aller Änderungen in einer HTTP-Anfrage sieht so aus, als könnte es einige Minuten dauern, also habe ich beschlossen, die Änderungen in mehrere HTTP-Anfragen zu zerlegen und den Fortschritt zu melden, wenn jede Anfrage erfolgreich ist.
Jetzt können einige Anforderungen im Batch Timeout sein und einige nicht.
Dann hatte ich die helle Idee, dass ich eine niedrige Zeitüberschreitung für die HTTP-Anfrage festlegen würde, um mit zu beginnen und es automatisch zu erhöhen. Der Stapel wird jedoch asynchron mit derselben Zeitüberschreitungseinstellung gesendet, und die Zeit wird für jeden Fehler angepasst. Das ist nicht gut.
Um dies zu lösen, wollte ich die Timeout-Einstellung verschieben, nachdem der Stapel abgeschlossen ist, dann auch alle Anfragen wiederholen.
Um ehrlich zu sein, bin ich nicht so sicher, dass eine automatische Timeout-Anpassung und Wiederholung ist so eine großartige Idee an erster Stelle. Und selbst wenn es so wäre, wäre es wahrscheinlich besser in einer Situation, in der http-Anfragen nacheinander gemacht wurden - was ich auch gesehen habe: https://stackoverflow.com/a/25730751/150342
'$ q.all' wird scheitern ganz egal was passiert. Sie könnten den Fehler abfangen, bevor jedes Versprechen gelöst wird und die Fehler vor dem '$ q.all' behandelt werden. –
Was ich meine, ist, anstatt eine einfache Versprechen in das Array zu schieben, eine Funktion, die * n * Mal versucht, dieses Versprechen zu lösen, wenn das fehlschlägt, dann alles scheitert, sollten Sie nur das Endergebnis auf dem $ q behandeln .all' Funktion. –
Tatsächlich habe ich festgestellt, dass '$ q.all' immer erfolgreich ist - deshalb überprüfe ich' fails.count() 'in der ersten Funktion, die an' then' übergeben wird. Habe ich irgendwo anders was falsch gemacht? – Colin