Jak sprawdzić wartość obietnicy?

146

Patrzę na ten przykład z dokumentacji Angulara dla, $qale myślę, że prawdopodobnie dotyczy to ogólnie obietnic. Poniższy przykład jest dosłownie skopiowany z ich dokumentów z dołączonym komentarzem:

promiseB = promiseA.then(function(result) {
  return result + 1;
});

// promiseB will be resolved immediately after promiseA is resolved and its value
// will be the result of promiseA incremented by 1

Nie wiem, jak to działa. Jeśli mogę odwołać .then()się do wyniku pierwszego .then(), powiązania ich w łańcuch, o którym wiem, że mogę, to promiseBjest to obiekt obietnicy, typu Object. To nie jest Number. Więc co mają na myśli, mówiąc „jego wartość będzie wynikiem obietnicy A zwiększonej o 1”?

Czy mam uzyskać do tego dostęp jako promiseB.valueczy coś takiego? W jaki sposób pomyślne wywołanie zwrotne może zwrócić obietnicę ORAZ zwrócić „wynik + 1”? Coś mi brakuje.

nazwa_użytkownika_tymczasowego
źródło
Zadałem podobne pytanie: Dlaczego Promise nie ma funkcji get ()?
Roland,
1
Czy to odpowiada na twoje pytanie? Jak zwrócić odpowiedź z wywołania asynchronicznego?
Heretic Monkey
To pytanie ma już 5 lat i zaakceptowaną odpowiedź ...
tymczasowy_user_name
@temporary_user_name: ludzie mogą oddawać bliskie głosy w dowolnym momencie, nawet na stare pytania.
halfer

Odpowiedzi:

141

promiseA„s thenfunkcja zwraca nową obietnicę ( promiseB), która jest natychmiast po rozwiązany promiseAzostał rozwiązany, jego wartość jest wartością z co jest zwracane z funkcji sukcesu wewnątrz promiseA.

W tym przypadku promiseAjest rozwiązywany z wartością - resulta następnie natychmiast rozwiązuje się promiseBz wartością result + 1.

Dostęp do wartości promiseBjest wykonywany w taki sam sposób, w jaki uzyskaliśmy dostęp do wyniku promiseA.

promiseB.then(function(result) {
    // here you can use the result of promiseB
});

Edycja grudnia 2019 : async/ awaitjest teraz standardem w JS, co pozwala na alternatywną składnię do podejścia opisanego powyżej. Możesz teraz napisać:

let result = await functionThatReturnsPromiseA();
result = result + 1;

Teraz nie ma obietnicyB, ponieważ rozpakowaliśmy wynik z użycia promiseA awaiti możesz z nim bezpośrednio pracować.

Jednak awaitmożna go używać tylko wewnątrz asyncfunkcji. Więc aby nieco pomniejszyć, powyższe musiało być zawarte w następujący sposób:

async function doSomething() {
    let result = await functionThatReturnsPromiseA();
    return result + 1;
}
Nachshon Schwartz
źródło
2
Teoretycznie obietnice są ich własnymi celami. zawierają wynik, do którego można uzyskać dostęp poprzez funkcję sukcesu obietnicy.
Nachshon Schwartz
2
Więc jeśli chcesz pracować z wartością zwracaną asynchronicznego wywołania zwrotnego obietnicy, musisz to zrobić wewnątrz innego asynchronicznego wywołania zwrotnego. Ma sens. Szukałem sposobu na uzyskanie jakiejś ostatecznej prymitywnej wartości zwracanej, ale przypuszczam, że byłoby to sprzeczne z rozsądkiem, biorąc pod uwagę kontekst.
tymczasowy_nazwa_użytkownika
2
@Aerovistae faktycznie, ES6 wprowadza generatory, które to umożliwiają, a ES7 wprowadza funkcje asynchroniczne - z których oba dają cukier składniowy ponad obietnicami, który sprawia, że ​​wygląda jak kod synchroniczny (uruchamiając maszynę stanu w tle) - więc trzymaj się mocno :)
Benjamin Gruenbaum
25

Kiedy obietnica zostanie rozwiązana / odrzucona, wywoła swoją procedurę obsługi sukcesu / błędu:

var promiseB = promiseA.then(function(result) {
   // do something with result
});

thenMetoda zwraca również obietnicę: promiseB, które zostaną rozwiązane / odrzucone w zależności od wartości powrotnej z obsługi sukcesu / błędu z promiseA .

Istnieją trzy możliwe wartości, które mogą zwrócić procedury obsługi sukcesu / błędu obietnicy A, które wpłyną na wynik promiseB:

1. Return nothing --> PromiseB is resolved immediately, 
   and undefined is passed to the success handler of promiseB
2. Return a value --> PromiseB is resolved immediately,
   and the value is passed to the success handler of promiseB
3. Return a promise --> When resolved, promiseB will be resolved. 
   When rejected, promiseB will be rejected. The value passed to
   the promiseB's then handler will be the result of the promise

Uzbrojeni w to zrozumienie, możesz zrozumieć następujące kwestie:

promiseB = promiseA.then(function(result) {
  return result + 1;
});

Następnie wywołanie natychmiast zwraca promiseB. Gdy obietnica A zostanie rozwiązana, przekazuje wynik do programu obsługi sukcesu obietnicy A. Ponieważ wartość zwracana jest wynikiem promiseA + 1, procedura obsługi sukcesu zwraca wartość (opcja 2 powyżej), więc promiseB rozwiąże problem natychmiast, a program obsługi sukcesu promiseB otrzyma wynik promiseA + 1.

bity pikseli
źródło
4

.thenfunction of promiseB otrzymuje to, co jest zwracane z .thenfunkcji promiseA.

tutaj zwraca promiseA jest liczbą, która będzie dostępna jako numberparametr w funkcji sukcesu promiseB. który następnie zostanie zwiększony o 1

harishr
źródło
3

Analiza komentarza nieco inaczej niż w obecnym rozumieniu może pomóc:

// promiseB will be resolved immediately after promiseA is resolved

Stanowi, że promiseBjest to obietnica, ale zostanie rozwiązana natychmiast po promiseArozwiązaniu. Z innego punktu widzenia oznacza to, że promiseA.then()zwraca obietnicę, do której jest przypisana promiseB.

// and its value will be the result of promiseA incremented by 1

Oznacza to, że wartość, która promiseAzostała rozwiązana, jest wartością, promiseBktóra otrzyma jako wartość successCallback:

promiseB.then(function (val) {
  // val is now promiseA's result + 1
});
Jason Cust
źródło
2

Odpowiedź pixelbits jest poprawna i zawsze powinieneś jej używać, .then()aby uzyskać dostęp do wartości obietnicy w kodzie produkcyjnym.

Istnieje jednak sposób, aby uzyskać dostęp do wartości obietnicy bezpośrednio po jej rozwiązaniu przy użyciu następującego nieobsługiwanego wewnętrznego powiązania node.js:

process.binding('util').getPromiseDetails(myPromise)[1]

OSTRZEŻENIE: process.binding nigdy nie miał być używany poza rdzeniem nodejs, a główny zespół nodejs aktywnie stara się go wycofać

https://github.com/nodejs/node/pull/22004 https://github.com/nodejs/node/issues/22064

Zeus Lalkaka
źródło
1

Ten przykład wydaje mi się oczywisty. Zwróć uwagę, jak czekasz na wynik, a więc przegapisz zwrot Obietnicy.

cryA = crypto.subtle.generateKey({name:'ECDH', namedCurve:'P-384'}, true, ["deriveKey", "deriveBits"])
Promise {<pending>}
cryB = await crypto.subtle.generateKey({name:'ECDH', namedCurve:'P-384'}, true, ["deriveKey", "deriveBits"])
{publicKey: CryptoKey, privateKey: CryptoKey}
Mistrz James
źródło
To musi być w funkcji asynchronicznej.
Samed
0
promiseA(pram).then(
     result => { 
     //make sure promiseA function allready success and response
     //do something here
}).catch(err => console.log(err)) => {
     // handle error with try catch
}
tomnyson
źródło
1
Chociaż ten kod może odpowiedzieć na pytanie, dostarczenie dodatkowego kontekstu dotyczącego tego, jak i dlaczego rozwiązuje problem, poprawiłoby długoterminową wartość odpowiedzi.
Alexander,
0

Możesz to łatwo zrobić za pomocą metody oczekiwania asynchronicznego w javascript.

Poniżej znajduje się przykład pobierania wartości obietnicy WebRTC przy użyciu limitu czasu.

function await_getipv4(timeout = 1000) {
    var t1 = new Date();
    while(!window.ipv4) {
        var stop = new Date() - t1 >= timeout;
        if(stop) {
            console.error('timeout exceeded for await_getipv4.');
            return false;
        }
    }
    return window.ipv4;
}

function async_getipv4() {
    var ipv4 = null;
    var findIP = new Promise(r=>{var w=window,a=new (w.RTCPeerConnection||w.mozRTCPeerConnection||w.webkitRTCPeerConnection)({iceServers:[]}),b=()=>{};a.createDataChannel("");a.createOffer(c=>a.setLocalDescription(c,b,b),b);a.onicecandidate=c=>{try{c.candidate.candidate.match(/([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g).forEach(r)}catch(e){}}})
    findIP.then(ip => window.ipv4 = ip);
    return await_getipv4();
};

OxFEEDFACE
źródło
Ważne jest, aby uruchomić ten fragment kodu nie tutaj, ale w prawdziwej przeglądarce, uważam, że jest to spowodowane piaskownicą.
OxFEEDFACE
0

W Node REPL, aby uzyskać połączenie DB, które było wartością obietnicy, przyjąłem następujące podejście:

let connection
try {
  (async () => {
    connection = await returnsAPromiseResolvingToConnection()
  })()
} catch(err) {
  console.log(err)
}

Linia z awaitnormalnie zwróciłaby obietnicę. Ten kod można wkleić do Node REPL lub, jeśli jest w index.jsnim zapisany , można go uruchomić w Bash z

node -i -e "$(< index.js)"

co pozostawia Cię w Node REPL po uruchomieniu skryptu z dostępem do ustawionej zmiennej. Aby potwierdzić, że funkcja asynchroniczna zwróciła, możesz connectionna przykład zarejestrować, a następnie możesz użyć zmiennej. Oczywiście nie chciałoby się liczyć na to, że funkcja asynchroniczna zostanie jeszcze rozwiązana dla dowolnego kodu w skrypcie poza funkcją asynchroniczną.

dmstack
źródło
0

Powyżej jest kilka dobrych odpowiedzi, a tutaj jest wersja funkcji ES6 Arrow

var something = async() => {
   let result = await functionThatReturnsPromiseA();
   return result + 1;
}
roopa l
źródło
0

Jestem powolnym uczniem obietnic javascript, domyślnie wszystkie funkcje asynchroniczne zwracają obietnicę, możesz opakować swój wynik jako:

(async () => {
//Optional "await"
  await yourAsyncFunctionOrPromise()
    .then(function (result) {
      return result +1;
    })
    .catch(function (error) {
      return error;
    })()
})

Wyrażenie await powoduje wstrzymanie wykonywania funkcji asynchronicznej do czasu rozliczenia Obietnicy (czyli wypełnienia lub odrzucenia) i wznowienie wykonywania funkcji asynchronicznej po spełnieniu. Po wznowieniu wartość wyrażenia await odpowiada wypełnionej Obietnicy . Jeśli obietnica zostanie odrzucona, wyrażenie await rzuca odrzuconą wartość . "

Przeczytaj więcej o oczekiwaniach i obietnicach w MDN Web Docs

Witryny LT
źródło
-5

Może ten mały przykład kodu Typescript pomoże.

private getAccount(id: Id) : Account {
    let account = Account.empty();
    this.repository.get(id)
        .then(res => account = res)
        .catch(e => Notices.results(e));
    return account;
}

Tutaj repository.get(id)zwraca a Promise<Account>. Przypisuję to zmiennej accountw theninstrukcji.

aahoogendoorn
źródło
1
Twój kod zwraca konto, zanim obietnica zostanie rozwiązana i dlatego jest przegłosowana. Twój kod zawsze zwraca Account.empty ();
Felype,