Wie erstelle ich mithilfe von ES6-Versprechungen ein Versprechen, ohne die Logik für dessen Lösung zu definieren? Hier ist ein einfaches Beispiel (etwas TypeScript):
var promises = {};
function waitFor(key: string): Promise<any> {
if (key in promises) {
return promises[key];
}
var promise = new Promise(resolve => {
// But I don't want to try resolving anything here :(
});
promises[key] = promise;
return promise;
}
function resolveWith(key: string, value: any): void {
promises[key].resolve(value); // Not valid :(
}
Mit anderen Versprechensbibliotheken ist das ganz einfach. JQuery's zum Beispiel:
var deferreds = {};
function waitFor(key: string): Promise<any> {
if (key in promises) {
return deferreds[key].promise();
}
var def = $.Deferred();
deferreds[key] = def;
return def.promise();
}
function resolveWith(key: string, value: any): void {
deferreds[key].resolve(value);
}
Die einzige Möglichkeit, dies zu tun, besteht darin, die Auflösungsfunktion irgendwo im Executor des Versprechens zu speichern, aber das scheint chaotisch zu sein, und ich bin nicht sicher, ob definiert ist, wann genau diese Funktion ausgeführt wird - wird sie immer sofort beim Aufbau ausgeführt?
Vielen Dank.
javascript
promise
es6-promise
Barguast
quelle
quelle
Antworten:
Gute Frage!
Der an den Versprechen-Konstruktor übergebene Resolver wird absichtlich synchron ausgeführt, um diesen Anwendungsfall zu unterstützen:
var deferreds = []; var p = new Promise(function(resolve, reject){ deferreds.push({resolve: resolve, reject: reject}); });
Dann zu einem späteren Zeitpunkt:
deferreds[0].resolve("Hello"); // resolve the promise with "Hello"
Der Grund, warum der Versprechungskonstruktor angegeben wird, ist folgender:
Manchmal passt es nicht und dafür läuft der Resolver synchron. Hier ist verwandte Lektüre zum Thema .
quelle
Promise.resolve
der Grenze gedacht und sie aufbewahrtthen
. Aber das sieht sauber aus und ich bin mir nicht mal sicher, ob die Bindungthen
funktionieren wird.Ich möchte hier meine 2 Cent hinzufügen. In Anbetracht der Frage " Erstellen eines es6-Versprechens, ohne es zu lösen " habe ich es gelöst, indem ich eine Wrapper-Funktion erstellt und stattdessen die Wrapper-Funktion aufgerufen habe . Code:
Angenommen, wir haben eine Funktion,
f
die ein Versprechen zurückgibt/** @return Promise<any> */ function f(args) { return new Promise(....) } // calling f() f('hello', 42).then((response) => { ... })
Jetzt möchte ich einen Anruf vorbereiten ,
f('hello', 42)
ohne ihn tatsächlich zu lösen:const task = () => f('hello', 42) // not calling it actually // later task().then((response) => { ... })
Hoffe das hilft jemandem :)
Referenzierung
Promise.all()
wie in den Kommentaren gefragt (und von @Joe Frambach beantwortet), wenn ich einen Aufruf von & , 2 Funktionen vorbereiten möchte, die Versprechen zurückgebenf1('super')
f2('rainbow')
const f1 = args => new Promise( ... ) const f2 = args => new Promise( ... ) const tasks = [ () => f1('super'), () => f2('rainbow') ] // later Promise.all(tasks.map(t => t())) .then(resolvedValues => { ... })
quelle
Promise.all()
?Wie wäre es mit einem umfassenderen Ansatz?
Sie könnten einen Konstruktor schreiben, der ein neues Versprechen zurückgibt, das mit
.resolve()
und.reject()
Methoden dekoriert ist .Sie würden sich wahrscheinlich dafür entscheiden, den Konstruktor zu benennen
Deferred
- ein Begriff, der in der Geschichte der Javascript-Versprechen einen hohen Stellenwert hat.function Deferred(fn) { fn = fn || function(){}; var resolve_, reject_; var promise = new Promise(function(resolve, reject) { resolve_ = resolve; reject_ = reject; fn(resolve, reject); }); promise.resolve = function(val) { (val === undefined) ? resolve_() : resolve_(val); return promise;//for chainability } promise.reject = function(reason) { (reason === undefined) ? reject_() : reject_(reason); return promise;//for chainability } promise.promise = function() { return promise.then(); //to derive an undecorated promise (expensive but simple). } return promise; }
Durch die Rückgabe eines dekorierten Promsie anstelle eines einfachen Objekts bleiben zusätzlich zu den Dekorationen alle natürlichen Methoden / Eigenschaften des Versprechens verfügbar.
Durch die Handhabung
fn
bleibt das Enthüllungsmuster auch dann verfügbar, wenn Sie es für eine verzögerte Verwendung benötigen / wählen.DEMO
Mit dem vorhandenen
Deferred()
Dienstprogramm ist Ihr Code praktisch identisch mit dem jQuery-Beispiel.var deferreds = {}; function waitFor(key: string): Promise<any> { if (key in promises) { return deferreds[key].promise(); } var def = Deferred(); deferreds[key] = def; return def.promise(); }
quelle
Deferred
einen Rückruf Parameter, sollte es wieder mit dem latenten b bezeichnet werden) Testen dervalue
/reason
fürundefined
absolut unnötig c).resolve
und.reject
nie brauchen werden angekettet d) Ihre.promise
Methode gibt kein nicht dekoriertes Versprechen zurückfn(promise)
(oder besser gesagtfn(deferred)
)fn(resolve, reject)
. Ja, ich sehe sicherlich einen Bedarf an "Resolver-Objekten", die irgendwo gespeichert und verfügbar gemacht werden können,.fulfill
und.reject
Methoden, aber ich denke, diese sollten die Versprechen-Schnittstelle nicht implementieren.new Promise(fn)
, nurresolve
und zu enthüllenreject
.when.js
Dokumentation von der Verwendung abrätwhen.defer
, erkennt sie dies anin certain (rare) scenarios it can be convenient to have access to both the promise and it's associated resolving functions
. Wenn diese Aussage geglaubt werden soll, sollte das, was ich oben anbiete, vernünftig erscheinen (in seltenen Szenarien).Im JavaScript-Land wird es langsam besser, aber dies ist ein Fall, in dem die Dinge immer noch unnötig kompliziert sind. Hier ist ein einfacher Helfer, um die Auflösungs- und Ablehnungsfunktionen aufzudecken:
Promise.unwrapped = () => { let resolve, reject, promise = new Promise((_resolve, _reject) => { resolve = _resolve, reject = _reject }) promise.resolve = resolve, promise.reject = reject return promise } // a contrived example let p = Promise.unwrapped() p.then(v => alert(v)) p.resolve('test')
Anscheinend gab es früher einen
Promise.defer
Helfer, aber selbst dieser bestand darauf, dass das zurückgestellte Objekt vom Versprechen selbst getrennt war ...quelle