Czytałem, że funkcje asynchroniczne oznaczone async
słowem kluczowym niejawnie zwracają obietnicę:
async function getVal(){
return await doSomethingAync();
}
var ret = getVal();
console.log(ret);
ale to nie jest spójne ... zakładając, że doSomethingAsync()
zwraca obietnicę, a słowo kluczowe await zwróci wartość z obietnicy, a nie z jej samej, wówczas moja funkcja getVal powinna zwrócić tę wartość, a nie ukrytą obietnicę.
Więc o co dokładnie chodzi? Czy funkcje oznaczone słowem kluczowym async niejawnie zwracają obietnice, czy też kontrolujemy to, co zwracają?
Może jeśli nie zwrócimy czegoś jawnie, to pośrednio zwrócą obietnicę ...?
Aby być bardziej zrozumiałym, istnieje różnica między powyższymi a
function doSomethingAync(charlie) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(charlie || 'yikes');
}, 100);
})
}
async function getVal(){
var val = await doSomethingAync(); // val is not a promise
console.log(val); // logs 'yikes' or whatever
return val; // but this returns a promise
}
var ret = getVal();
console.log(ret); //logs a promise
W moim streszczeniu zachowanie jest rzeczywiście niezgodne z tradycyjnymi instrukcjami powrotu. Wygląda na to, że gdy jawnie zwrócisz wartość, która nie jest obietnicą z async
funkcji, wymusi to zawinięcie jej w obietnicę. Nie mam z tym dużego problemu, ale przeciwstawia się normalnemu JS.
źródło
console.log
pokazuje?Odpowiedzi:
Wartość zwracana zawsze będzie obietnicą. Jeśli nie zwrócisz wyraźnie obietnicy, wartość, którą zwrócisz, zostanie automatycznie umieszczona w obietnicy.
To samo, nawet jeśli istnieje
await
.Promises automatycznie rozpakowuje, więc jeśli zwrócisz obietnicę wartości z
async
funkcji, otrzymasz obietnicę wartości (nie obietnicę obietnicy wartości).ES6 ma funkcje, które nie zwracają dokładnie tej samej wartości co
return
. Te funkcje nazywane są generatorami.źródło
Spojrzałem na specyfikację i znalazłem następujące informacje. Krótka wersja jest taka, że
async function
desukrates do generatora, który dajePromise
s. Więc tak, funkcje asynchroniczne zwracają obietnice .Zgodnie ze specyfikacją tc39 , następujące są prawdziwe:
Cukry do:
Gdzie
spawn
„jest wywołaniem następującego algorytmu”:źródło
async function
zasync function*
. Ten pierwszy po prostu zwraca obietnicę. Ten ostatni zwraca generator, który daje obietnice.Po prostu dodaj await przed swoją funkcją, gdy ją wywołasz:
źródło
async nie zwraca obietnicy, słowo kluczowe await oczekuje na rozwiązanie obietnicy. async to ulepszona funkcja generatora, która działa trochę jak yield
Myślę, że składnia (nie jestem pewien w 100%) jest
async function* getVal() {...}
Funkcje generatora ES2016 działają trochę tak. Stworzyłem program obsługi bazy danych oparty na żmudnym programie, który programujesz w ten sposób
Zwróć uwagę, jak po prostu programuję to jako normalną synchroniczną, szczególnie w
yield connection.execSql
i o godzyield connection.callProcedure
Funkcja db.exec jest dość typowym generatorem opartym na Promise
źródło