Theorie
Native async
Funktionen können bei der Konvertierung in Zeichenfolgen identifiziert werden :
asyncFn[Symbol.toStringTag] === 'AsyncFunction'
Oder vom AsyncFunction
Konstruktor:
const AsyncFunction = (async () => {}).constructor;
asyncFn instanceof AsyncFunction === true
Dies funktioniert nicht mit der Babel / TypeScript-Ausgabe, da asyncFn
es sich bei der regulären Funktion im transpilierten Code um eine Instanz von Function
oder GeneratorFunction
nicht handelt AsyncFunction
. Um sicherzustellen, dass im transpilierten Code keine Fehlalarme für Generator- und reguläre Funktionen ausgegeben werden:
const AsyncFunction = (async () => {}).constructor;
const GeneratorFunction = (function* () => {}).constructor;
(asyncFn instanceof AsyncFunction && AsyncFunction !== Function && AsyncFunction !== GeneratorFunction) === true
Da native async
Funktionen 2017 offiziell in Node.js eingeführt wurden, bezieht sich die Frage wahrscheinlich auf die Babel-Implementierung von async
Funktionen, die sich auf transform-async-to-generator
das Transpilieren async
in Generatorfunktionen stützen und möglicherweise auch transform-regenerator
zum Transpilieren von Generatoren in reguläre Funktionen verwendet werden.
Das Ergebnis des async
Funktionsaufrufs ist ein Versprechen. Dem Vorschlag zufolge kann ein Versprechen oder ein Nichtversprechen weitergegeben werden await
, await callback()
was universell ist.
Es gibt nur wenige Randfälle, in denen dies erforderlich sein kann. Zum Beispiel verwenden native async
Funktionen native Versprechen intern und greifen nicht global auf, Promise
wenn ihre Implementierung geändert wurde:
let NativePromise = Promise;
Promise = CustomPromiseImplementation;
Promise.resolve() instanceof Promise === true
(async () => {})() instanceof Promise === false;
(async () => {})() instanceof NativePromise === true;
Dies kann das Funktionsverhalten beeinflussen (dies ist ein bekanntes Problem für die Implementierung von Angular und Zone.js Versprechen ). Selbst dann ist es vorzuziehen, zu erkennen, dass der Funktionsrückgabewert nicht als Promise
Instanz erwartet wird, anstatt zu erkennen, dass es sich um eine Funktion handelt async
, da dasselbe Problem auf jede Funktion anwendbar ist, die eine alternative Versprechenimplementierung verwendet, und nicht nur async
( die Lösung für dieses Winkelproblem besteht darin, die async
Rückgabe zu verpacken Wert mit Promise.resolve
).
Trainieren
Von außen ist async
Funktion nur eine Funktion, die bedingungslos native Versprechen zurückgibt, daher sollte sie wie eine behandelt werden. Selbst wenn eine Funktion einmal definiert wurde async
, kann sie irgendwann transpiliert werden und zu einer regulären Funktion werden.
Eine Funktion, die ein Versprechen zurückgeben kann
In ES6 kann eine Funktion, die möglicherweise ein Versprechen zurückgibt, mit Promise.resolve
(lässt synchrone Fehler) oder einem umschlossenen Promise
Konstruktor (behandelt synchrone Fehler) verwendet werden:
Promise.resolve(fnThatPossiblyReturnsAPromise())
.then(result => ...);
new Promise(resolve => resolve(fnThatPossiblyReturnsAPromiseOrThrows()))
.then(result => ...);
In ES2017 geschieht dies mit await
(so soll das Beispiel aus der Frage geschrieben werden):
let result = await fnThatPossiblyReturnsAPromiseOrThrows();
...
Eine Funktion, die ein Versprechen zurückgeben sollte
Die Überprüfung, ob ein Objekt ein Versprechen ist, ist eine separate Frage , sollte jedoch im Allgemeinen nicht zu streng oder locker sein, um Eckfälle abzudecken. instanceof Promise
funktioniert möglicherweise nicht, wenn global Promise
ersetzt wurde Promise !== (async () => {})().constructor
. Dies kann passieren, wenn Angular- und Nicht-Angular-Anwendungen eine Schnittstelle bilden.
Eine Funktion, die erforderlich ist async
, dh immer ein Versprechen zurückzugeben, sollte zuerst aufgerufen werden. Anschließend wird der zurückgegebene Wert als Versprechen überprüft:
let promise = fnThatShouldReturnAPromise();
if (promise && typeof promise.then === 'function' && promise[Symbol.toStringTag] === 'Promise') {
} else {
throw new Error('async function expected');
}
TL; DR: async
Funktionen sollten nicht von regulären Funktionen unterschieden werden, die Versprechen zurückgeben. Es gibt keinen zuverlässigen Weg und keinen praktischen Grund, nicht native transpilierte async
Funktionen zu erkennen .
await
ein Nicht-Versprechen haben, wird es trotzdem automatisch verpackt)