
Benjamin Grünbaum
Ich möchte mit Versprechungen arbeiten, aber ich habe eine Rückruf-API in einem Format wie:
1. DOM-Laden oder anderes einmaliges Ereignis:
window.onload; // set to callback
...
window.onload = function() {
};
2. Einfacher Rückruf:
function request(onChangeHandler) {
...
}
request(function() {
// change happened
...
});
3. Node-Style-Callback (“Nodeback”):
function getStuff(dat, callback) {
...
}
getStuff("dataParam", function(err, data) {
...
})
4. Eine ganze Bibliothek mit Node-Style-Callbacks:
API;
API.one(function(err, data) {
API.two(function(err, data2) {
API.three(function(err, data3) {
...
});
});
});
Wie arbeite ich mit der API in Versprechungen, wie „verspreche“ ich sie?

Benjamin Grünbaum
Versprechen haben einen Status, sie beginnen als ausstehend und können sich wie folgt begleichen:
- erfüllt was bedeutet, dass die Berechnung erfolgreich abgeschlossen wurde.
- abgelehnt was bedeutet, dass die Berechnung fehlgeschlagen ist.
Versprechen Sie wiederkehrende Funktionen sollte niemals werfen, sollten sie stattdessen Ablehnungen zurückgeben. Das Auslösen einer Versprechen-Rückgabefunktion zwingt Sie dazu, sowohl a zu verwenden } catch {
und ein .catch
. Personen, die versprochene APIs verwenden, erwarten nicht, dass Versprechen geworfen werden. Wenn Sie nicht sicher sind, wie asynchrone APIs in JS funktionieren, sehen Sie sich bitte zuerst diese Antwort an.
1. DOM-Laden oder anderes einmaliges Ereignis:
Das Erstellen von Zusagen bedeutet also im Allgemeinen, anzugeben, wann sie abgerechnet werden – das heißt, wann sie in die Phase „Erfüllt“ oder „Abgelehnt“ wechseln, um anzuzeigen, dass die Daten verfügbar sind (und mit ihnen zugegriffen werden kann). .then
).
Mit modernen Promise-Implementierungen, die das unterstützen Promise
Konstruktor wie native ES6 verspricht:
function load() {
return new Promise(function(resolve, reject) {
window.onload = resolve;
});
}
Sie würden dann das resultierende Versprechen wie folgt verwenden:
load().then(function() {
// Do things after onload
});
Mit Bibliotheken, die Deferred unterstützen (verwenden wir $q für dieses Beispiel hier, aber wir werden später auch jQuery verwenden):
function load() {
var d = $q.defer();
window.onload = function() { d.resolve(); };
return d.promise;
}
Oder mit einer jQuery-ähnlichen API, die sich auf ein Ereignis einklinkt, das einmal passiert:
function done() {
var d = $.Deferred();
$("#myObject").once("click",function() {
d.resolve();
});
return d.promise();
}
2. Einfacher Rückruf:
Diese APIs sind ziemlich gebräuchlich, da Callbacks in JS üblich sind. Schauen wir uns den üblichen Fall des Habens an onSuccess
und onFail
:
function getUserData(userId, onLoad, onFail) { …
Mit modernen Promise-Implementierungen, die das unterstützen Promise
Konstruktor wie native ES6 verspricht:
function getUserDataAsync(userId) {
return new Promise(function(resolve, reject) {
getUserData(userId, resolve, reject);
});
}
Mit Bibliotheken, die Deferred unterstützen (verwenden wir für dieses Beispiel hier jQuery, aber wir haben oben auch $q verwendet):
function getUserDataAsync(userId) {
var d = $.Deferred();
getUserData(userId, function(res){ d.resolve(res); }, function(err){ d.reject(err); });
return d.promise();
}
jQuery bietet auch eine $.Deferred(fn)
Form, die den Vorteil hat, dass wir einen Ausdruck schreiben können, der sehr genau nachahmt new Promise(fn)
Form, wie folgt:
function getUserDataAsync(userId) {
return $.Deferred(function(dfrd) {
getUserData(userId, dfrd.resolve, dfrd.reject);
}).promise();
}
Hinweis: Hier nutzen wir die Tatsache aus, dass eine jQuery deferred ist resolve
und reject
Methoden sind “abnehmbar”; dh. sie sind an die gebunden Beispiel einer jQuery.Deferred(). Nicht alle Bibliotheken bieten diese Funktion.
3. Node-Style-Callback (“Nodeback”):
Rückrufe im Knotenstil (Nodebacks) haben ein bestimmtes Format, bei dem der Rückruf immer das letzte Argument ist und sein erster Parameter ein Fehler ist. Lassen Sie uns zuerst einen manuell versprechen:
getStuff("dataParam", function(err, data) { …
Zu:
function getStuffAsync(param) {
return new Promise(function(resolve, reject) {
getStuff(param, function(err, data) {
if (err !== null) reject(err);
else resolve(data);
});
});
}
Mit Verzögerungen können Sie Folgendes tun (lassen Sie uns für dieses Beispiel Q verwenden, obwohl Q jetzt die neue Syntax unterstützt, die Sie bevorzugen sollten):
function getStuffAsync(param) {
var d = Q.defer();
getStuff(param, function(err, data) {
if (err !== null) d.reject(err);
else d.resolve(data);
});
return d.promise;
}
Im Allgemeinen sollten Sie die Dinge nicht zu sehr manuell versprechen, die meisten Versprechungsbibliotheken, die für Node entwickelt wurden, sowie native Versprechungen in Node 8+ haben eine eingebaute Methode zum Versprechen von Nodebacks. Zum Beispiel
var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q
var getStuffAsync = util.promisify(getStuff); // Native promises, node only
4. Eine ganze Bibliothek mit Node-Style-Callbacks:
Hier gibt es keine goldene Regel, Sie versprechen es ihnen nacheinander. Einige Promise-Implementierungen ermöglichen es Ihnen jedoch, dies in großen Mengen zu tun, zum Beispiel in Bluebird, das Konvertieren einer Nodeback-API in eine Promise-API ist so einfach wie:
Promise.promisifyAll(API);
Oder mit einheimische Versprechen in Knoten:
const { promisify } = require('util');
const promiseAPI = Object.entries(API).map(([key, v]) => ({key, fn: promisify(v)}))
.reduce((o, p) => Object.assign(o, {[p.key]: p.fn}), {});
Anmerkungen:
- Natürlich, wenn Sie in einem sind
.then
Handler brauchen Sie nichts zu versprechen. Zurückgeben eines Versprechens von a .then
Der Handler wird mit dem Wert dieses Versprechens auflösen oder ablehnen. Werfen von a .then
Der Handler ist auch eine gute Übung und wird das Versprechen ablehnen – dies ist das berühmte Versprechen der Wurfsicherheit.
- In einem tatsächlichen
onload
Fall sollten Sie verwenden addEventListener
eher, als onX
.

efkan
Heute kann ich verwenden Promise
in Node.js
als einfache Javascript-Methode.
Ein einfaches und grundlegendes Beispiel für Promise
(mit KUSS Weg):
Einfach JavaScript-Async-API-Code:
function divisionAPI (number, divider, successCallback, errorCallback) {
if (divider == 0) {
return errorCallback( new Error("Division by zero") )
}
successCallback( number / divider )
}
Promise
JavaScript-Async-API-Code:
function divisionAPI (number, divider) {
return new Promise(function (fulfilled, rejected) {
if (divider == 0) {
return rejected( new Error("Division by zero") )
}
fulfilled( number / divider )
})
}
(Ich empfehle den Besuch diese schöne Quelle)
Ebenfalls Promise
kann mit zusammen verwendet werden async\await
in ES7
um den Programmablauf auf a warten zu lassen fullfiled
Ergebnis wie folgt:
function getName () {
return new Promise(function (fulfilled, rejected) {
var name = "John Doe";
// wait 3000 milliseconds before calling fulfilled() method
setTimeout (
function() {
fulfilled( name )
},
3000
)
})
}
async function foo () {
var name = await getName(); // awaits for a fulfilled result!
console.log(name); // the console writes "John Doe" after 3000 milliseconds
}
foo() // calling the foo() method to run the code
Eine weitere Verwendung mit demselben Code durch Verwendung .then()
Methode
function getName () {
return new Promise(function (fulfilled, rejected) {
var name = "John Doe";
// wait 3000 milliseconds before calling fulfilled() method
setTimeout (
function() {
fulfilled( name )
},
3000
)
})
}
// the console writes "John Doe" after 3000 milliseconds
getName().then(function(name){ console.log(name) })
Promise
kann auch auf jeder Plattform verwendet werden, die auf Node.js basiert, wie z react-native
.
Bonus: Ein hybrid Methode
(Es wird davon ausgegangen, dass die Callback-Methode zwei Parameter als Fehler und Ergebnis hat.)
function divisionAPI (number, divider, callback) {
return new Promise(function (fulfilled, rejected) {
if (divider == 0) {
let error = new Error("Division by zero")
callback && callback( error )
return rejected( error )
}
let result = number / divider
callback && callback( null, result )
fulfilled( result )
})
}
Die obige Methode kann das Ergebnis für altmodische Callback- und Promise-Verwendungen beantworten.
Hoffe das hilft.

Shiva Kannan
Vor dem Konvertieren einer Funktion als Promise In Node.JS
var request = require('request'); //http wrapped module
function requestWrapper(url, callback) {
request.get(url, function (err, response) {
if (err) {
callback(err);
}else{
callback(null, response);
}
})
}
requestWrapper(url, function (err, response) {
console.log(err, response)
})
Nach der Konvertierung
var request = require('request');
function requestWrapper(url) {
return new Promise(function (resolve, reject) { //returning promise
request.get(url, function (err, response) {
if (err) {
reject(err); //promise reject
}else{
resolve(response); //promise resolve
}
})
})
}
requestWrapper('http://localhost:8080/promise_request/1').then(function(response){
console.log(response) //resolve callback(success)
}).catch(function(error){
console.log(error) //reject callback(failure)
})
Falls Sie mehrere Anfragen bearbeiten müssen
var allRequests = [];
allRequests.push(requestWrapper('http://localhost:8080/promise_request/1'))
allRequests.push(requestWrapper('http://localhost:8080/promise_request/2'))
allRequests.push(requestWrapper('http://localhost:8080/promise_request/5'))
Promise.all(allRequests).then(function (results) {
console.log(results);//result will be array which contains each promise response
}).catch(function (err) {
console.log(err)
});

Löwe
Ich glaube nicht window.onload
Der Vorschlag von @Benjamin funktioniert immer, da er nicht erkennt, ob er nach dem Laden aufgerufen wird. Ich bin schon oft davon gebissen worden. Hier ist eine Version, die immer funktionieren sollte:
function promiseDOMready() {
return new Promise(function(resolve) {
if (document.readyState === "complete") return resolve();
document.addEventListener("DOMContentLoaded", resolve);
});
}
promiseDOMready().then(initOnLoad);

Josiah Nyarega
Eine einfache generische Funktion, die ich normalerweise verwende.
const promisify = (fn, ...args) => {
return new Promise((resolve, reject) => {
fn(...args, (err, data) => {
if (err) {
return reject(err);
}
resolve(data);
});
});
};
Wie man es benutzt
- Die Funktion
promisify
akzeptiert eine Funktion mit einem Callback:
const cb = (result) => `The result is ${result}`;
const sum = (a, b, cb) => {
const result = a + b;
cb(result); // passing args to the callback function
}
// using the util
promise = promisify(sum, 3, 1, cb);
promise.then(x => console.log(x)) // 4
Sie suchen wahrscheinlich nicht nach dieser Antwort, aber dies wird Ihnen helfen, das Innenleben der verfügbaren Dienstprogramme zu verstehen
Node.js 8.0.0 enthält eine neue util.promisify()
API, mit der Standard-APIs im Callback-Stil von Node.js in eine Funktion eingeschlossen werden können, die ein Promise zurückgibt. Ein Beispiel für die Verwendung von util.promisify()
ist unten gezeigt.
const fs = require('fs');
const util = require('util');
const readFile = util.promisify(fs.readFile);
readFile('/some/file')
.then((data) => { /** ... **/ })
.catch((err) => { /** ... **/ });
Sehen Verbesserte Unterstützung für Promises

Bruno
Im Release Candidate für Node.js 8.0.0 gibt es ein neues Dienstprogramm, util.promisify
(Ich habe darüber geschrieben util.promisify), die die Fähigkeit verkörpert, jede beliebige Funktion zu versprechen.
Es unterscheidet sich nicht wesentlich von den in den anderen Antworten vorgeschlagenen Ansätzen, hat jedoch den Vorteil, dass es sich um eine Kernmethode handelt und keine zusätzlichen Abhängigkeiten erforderlich sind.
const fs = require('fs');
const util = require('util');
const readFile = util.promisify(fs.readFile);
Dann hast du ein readFile
Methode, die eine native zurückgibt Promise
.
readFile('./notes.txt')
.then(txt => console.log(txt))
.catch(...);
9865000cookie-checkWie konvertiere ich eine vorhandene Callback-API in Promises?yes
Ich habe meine eigene Antwort gepostet, aber Antworten, die erläutern, wie dies für eine bestimmte Bibliothek oder unter anderen Umständen geht, und auch Änderungen sind sehr willkommen.
– Benjamin Grünbaum
19. März 2014 um 22:49 Uhr
@Bergi Das ist eine interessante Idee, ich habe versucht, eine allgemeine Antwort zu geben, die die beiden gängigen Ansätze (Promise-Konstruktor und zurückgestelltes Objekt) verwendet. Ich habe versucht, die beiden Alternativen in Antworten zu geben. Ich stimme zu, dass RTFMing dieses Problem löst, aber wir stoßen oft sowohl hier als auch im Bugtracker auf dieses Problem, also dachte ich, dass eine “kanonische Frage” vorhanden ist – ich denke, RTFMing löst etwa 50% der Probleme im JS-Tag: D If Sie haben einen interessanten Einblick, den Sie in einer Antwort beitragen oder bearbeiten können. Dies wäre sehr willkommen.
– Benjamin Grünbaum
20. März 2014 um 13:24 Uhr
Hat das Erstellen von a
new Promise
einen erheblichen Overhead hinzufügen? Ich möchte alle meine synchronen Noje.js-Funktionen in ein Promise packen, um den gesamten synchronen Code aus meiner Node-App zu entfernen, aber ist dies die beste Vorgehensweise? Mit anderen Worten, eine Funktion, die ein statisches Argument (z. B. eine Zeichenfolge) akzeptiert und ein berechnetes Ergebnis zurückgibt, sollte ich das in ein Versprechen verpacken? …Ich habe irgendwo gelesen, dass Sie keinen synchronen Code in Nodejs haben sollten.– Ronnie Royston
21. Januar 2019 um 19:12 Uhr
@RonRoyston nein, es ist keine gute Idee, synchrone Aufrufe mit Versprechen zu umschließen – nur asynchrone Aufrufe, die möglicherweise E / A ausführen
– Benjamin Grünbaum
22. Januar 2019 um 15:12 Uhr