Führen Sie mehrere Aufgaben asynchron aus und geben Sie das erste erfolgreiche Ergebnis in der JavaScript-Funktion zurück
Ich muss eine JavaScript-Funktion schreiben, die dem Aufrufer einige Daten zurückgibt.
In dieser Funktion habe ich mehrere Möglichkeiten, Daten abzurufen, d. H.
Suche aus dem CacheVon HTML5 LocalStorage abrufenVom REST-Backend abrufen (Bonus: Neue Daten wieder in den Cache stellen)Das Beenden jeder Option kann einige Zeit in Anspruch nehmen und erfolgreich sein oder fehlschlagen.
Was ich tun möchte, ist, alle diese drei Optionen asynchron / parallel auszuführen und das Ergebnis zurückzugeben, wer zuerst zurückgibt.
Ich verstehe, dass eine parallele Ausführung in JavaScript nicht möglich ist, da es sich um einen Singlethread handelt, aber ich möchte sie zumindest asynchron ausführen und die anderen Tasks abbrechen, wenn eine von ihnen erfolgreich zurückgegeben wird.
Ich habe noch eine Frage.
Vorzeitige Rückkehr und weitere Ausführung der verbleibenden Aufgabe in einer JavaScript-Funktion.
Beispiel Pseudocode:
function getOrder(id) {
var order;
// early return if the order is found in cache.
if (order = cache.get(id)) return order;
// continue to get the order from the backend REST API.
order = cache.put(backend.get(id));
return order;
}
Bitte geben Sie Hinweise zur Implementierung dieser Anforderungen in JavaScript.
Bisher entdeckte Lösungen:Schnellstes ErgebnisJavaScript ES6-LösungRef:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Promise.race (iterabel)
Gibt ein Versprechen zurück, das aufgelöst wird, wenn das erste Versprechen in der Iterationsfolge aufgelöst wird.
var p1 = new Promise(function(resolve, reject) { setTimeout(resolve, 500, "one"); });
var p2 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, "two"); });
Promise.race([p1, p2]).then(function(value) {
// value == "two"
});
Java / Groovy-LösungRef:http://gpars.org/1.1.0/guide/guide/single.html
import groovyx.gpars.dataflow.Promise
import groovyx.gpars.dataflow.Select
import groovyx.gpars.group.DefaultPGroup
import java.util.concurrent.atomic.AtomicBoolean
/**
* Demonstrates the use of dataflow tasks and selects to pick the fastest result of concurrently run calculations.
* It shows a waz to cancel the slower tasks once a result is known
*/
final group = new DefaultPGroup()
final done = new AtomicBoolean()
group.with {
Promise p1 = task {
sleep(1000)
if (done.get()) return
10 * 10 + 1
}
Promise p2 = task {
sleep(1000)
if (done.get()) return
5 * 20 + 2
}
Promise p3 = task {
sleep(1000)
if (done.get()) return
1 * 100 + 3
}
final alt = new Select(group, p1, p2, p3, Select.createTimeout(500))
def result = alt.select()
done.set(true)
println "Result: " + result
}
Early Return und Interaktive Funktion
Angular Promises kombiniert mit ES6-Generatoren ???angular.module('org.common')
.service('SpaceService', function ($q, $timeout, Restangular, $angularCacheFactory) {
var _spacesCache = $angularCacheFactory('spacesCache', {
maxAge: 120000, // items expire after two min
deleteOnExpire: 'aggressive',
onExpire: function (key, value) {
Restangular.one('organizations', key).getList('spaces').then(function (data) {
_spacesCache.put(key, data);
});
}
});
/**
* @class SpaceService
*/
return {
getAllSpaces: function (orgId) {
var deferred = $q.defer();
var spaces;
if (spaces = _spacesCache.get(orgId)) {
deferred.resolve(spaces);
} else {
Restangular.one('organizations', orgId).getList('spaces').then(function (data) {
_spacesCache.put(orgId, data);
deferred.resolve(data);
} , function errorCallback(err) {
deferred.reject(err);
});
}
return deferred.promise;
},
getAllSpaces1: function (orgId) {
var deferred = $q.defer();
var spaces;
var timerID = $timeout(
Restangular.one('organizations', orgId).getList('spaces').then(function (data) {
_spacesCache.put(orgId, data);
deferred.resolve(data);
}), function errorCallback(err) {
deferred.reject(err);
}, 0);
deferred.notify('Trying the cache now...'); //progress notification
if (spaces = _spacesCache.get(orgId)) {
$timeout.cancel(timerID);
deferred.resolve(spaces);
}
return deferred.promise;
},
getAllSpaces2: function (orgId) {
// set up a dummy canceler
var canceler = $q.defer();
var deferred = $q.defer();
var spaces;
$timeout(
Restangular.one('organizations', orgId).withHttpConfig({timeout: canceler.promise}).getList('spaces').then(function (data) {
_spacesCache.put(orgId, data);
deferred.resolve(data);
}), function errorCallback(err) {
deferred.reject(err);
}, 0);
if (spaces = _spacesCache.get(orgId)) {
canceler.resolve();
deferred.resolve(spaces);
}
return deferred.promise;
},
addSpace: function (orgId, space) {
_spacesCache.remove(orgId);
// do something with the data
return '';
},
editSpace: function (space) {
_spacesCache.remove(space.organization.id);
// do something with the data
return '';
},
deleteSpace: function (space) {
console.table(space);
_spacesCache.remove(space.organization.id);
return space.remove();
}
};
});