2016-08-10 20 views
16

Mój kod:Obietnica oczekiwaniu

let AuthUser = data => { 
    return google.login(data.username, data.password).then(token => { return token }) 
} 

A kiedy próbuję uruchomić coś takiego:

let userToken = AuthUser(data) 
console.log(userToken) 

Dostaję:

Promise { <pending> } 

ale dlaczego?

Moim głównym celem jest uzyskanie tokena z google.login(data.username, data.password), który zwraca obietnicę, do zmiennej. I dopiero potem przeprowadź niektóre działania.

+7

Jest to obietnica. Obietnica nie jest realizowana zaraz po jej utworzeniu. Dlatego nazywa się to obietnicą. Obiecuje zrobić coś później. –

+0

@ LoïcFaure-Lacroix, zobacz ten artykuł: https://medium.com/@bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8#.w234uo7h3 – Src

+0

@ LoïcFaure-Lacroix spójrz na 'getFirstUser' function – Src

Odpowiedz

29

Obietnica będzie zawsze rejestrowana, dopóki jej wyniki nie zostaną jeszcze rozwiązane. Niezależnie od stanu obietnicy (rozwiązany lub w toku) należy wywołać .then na obietnicy się uchwycić wyniki:

let AuthUser = function(data) { 
    return google.login(data.username, data.password).then(token => { return token }) 
} 

let userToken = AuthUser(data) 
console.log(userToken) // Promise { <pending> } 

userToken.then(function(result) { 
    console.log(result) //will log results. 
}) 

dlaczego tak jest?

obietnice są tylko w przód, można je rozwiązać tylko raz, a ich wartość można przekazać tylko do .then /.złapać

Szczegóły

istnieje nieporozumienie w sekcji komentarzy na jedną odpowiedź poniżej temat zwrotu następnie powróci do tylko jego funkcji, ostatecznie nic nie robi. .then(token => { return token; })

Cytowanie zostały argument jest (przejście go, aby upewnić się nikt nie myśli, że to jest poprawna)

Ultimately your callback token => { return token; } does nothing; instead, your input to then() needs to be a function that actually handles the token in some way.

Zgodnie z obietnicami/A + specyfikacji:

The promise resolution procedure is an abstract operation taking as input a promise and a value, which we denote as [[Resolve]](promise, x). If x is a thenable, it attempts to make promise adopt the state of x, under the assumption that x behaves at least somewhat like a promise. Otherwise, it fulfills promise with the value x.

This treatment of thenables allows promise implementations to interoperate, as long as they expose a Promises/A+-compliant then method. It also allows Promises/A+ implementations to “assimilate” nonconformant implementations with reasonable then methods.

Ten szczegół realizacja jest mało trudny do przeanalizowania, więc możemy go rozbić.

Reguła jest taka, że ​​jeśli funkcja, która jest w procedurze obsługi, zwraca wartość, obietnica rozpatruje/odrzuca tę wartość, a jeśli funkcja zwraca obietnicę, to co się stanie, następna klauzula będzie wtedy klauzula obietnicy zwraca tę funkcję, więc w tym przypadku pierwszy przykład przechodzi przez normalną sekwencję thens i wypisuje wartości, jak można się było spodziewać, w drugim przykładzie, obiekt obietnicy, który zostanie zwrócony, gdy wykonasz Obietnicę. resolve ("bbb") to wtedy jest wywoływane podczas łączenia (dla wszystkich intencji i celów). Sposób, w jaki faktycznie działa, opisano bardziej szczegółowo poniżej.

1. Zwrot z funkcji .then będzie wartością rozstrzygnięcia obietnicy.

Przykład:

function initPromise() { 
    return new Promise(function(res,rej) { 
    res("initResolve"); 
    }) 
} 

initPromise().then(function(result) { 
    console.log(result); // "initResolve" 
    return "normalReturn"; 
}) 
.then(function(result) { 
    console.log(result); // "normalReturn" 
}); 

2. Jeśli funkcja .then zwraca obietnicę, wówczas postanowienie o jego obietnicy będzie rozwiązać jego najbliższego .then zasadzie.

Przykład:

function initPromise() { 
    return new Promise(function(res,rej) { 
    res("initResolve"); 
    }) 
} 
initPromise().then(function(result) { 
    console.log(result); // "initResolve" 
    return new Promise(function(resolve, reject) { 
     setTimeout(function() { 
      resolve("secondPromise"); 
     }, 1000) 
    }) 
}) 
.then(function(result) { 
    console.log(result); // "secondPromise" 
}); 
+0

Twoja pierwsza nie działa. 'Uncaught SyntaxError: Nieoczekiwany token.". Drugi potrzebuje zwrotu dla 'Promise' – zamil

+0

@zamil, musisz wywołać funkcję, jak w drugim przykładzie. nie możesz '.then' na niezasłużonej funkcji. zaktualizował odpowiedź – Bamieh

0

Zobacz sekcję MDN na Promises. W szczególności spojrzeć na typ zwracanej then().

Aby się zalogować, użytkownik-agent musi przesłać żądanie do serwera i czekać na odpowiedź. Ponieważ całkowite zatrzymanie aplikacji w trakcie żądania w obie strony zwykle prowadzi do złego doświadczenia użytkownika, praktycznie każda funkcja JS, która zaloguje się (lub wykona jakąkolwiek inną formę interakcji serwera) użyje obietnicy, lub czegoś bardzo podobnego , aby dostarczyć wyniki asynchronicznie.

Teraz również zauważyć, że return wypowiedzi są zawsze oceniane w kontekście funkcji pojawiania się więc, gdy pisał:.

let AuthUser = data => { 
    return google 
    .login(data.username, data.password) 
    .then(token => { 
     return token; 
    }); 
}; 

oświadczenie return token; oznaczało, że funkcja anonimowa były przekazywane do then() powinny powrócić token, a nie funkcja AuthUser. To, co zwraca AuthUser, jest wynikiem wywołania google.login(username, password).then(callback);, co jest przypadkiem obietnicą.

Ostatecznie twój oddzwonienie token => { return token; } nic nie robi; zamiast tego twoje wejście do then() musi być funkcją, która faktycznie obsługuje token w pewien sposób.

+0

@Src Napisałem odpowiedź, zanim osoba pytająca wyjaśniła, że ​​szuka sposobu na * synchroniczne * zwrócenie wartości i bez przyjmowania założeń dotyczących środowiska programistycznego lub wersji językowej poza to, co można wywnioskować za pomocą fragmentu kodu - czyli , można bezpiecznie założyć ES6, ale niekoniecznie ES7. –

+0

@AhmadBamieh Dobra, zrobi. Zakładam, że problem polega na tym, że źle zrozumiałem, w jaki sposób 'return' jest traktowane przy użyciu nowej składni (ish) zamknięcia, w którym to przypadku - cóż, zdecydowanie go potępiam, ale błąd nadal jest mój i przepraszam za to. –

+0

Mogę zrozumieć, jak się czujesz, ponieważ powrót powinien być zsynchronizowany, i powinien zwrócić kontrolę nad swoim rozmówcą, który jest anonimową funkcją. ale wytłumaczeniem dla ciebie jest to, że powinieneś zauważyć, że zwracany typ then() jest nowym obiektem Promise, stąd wartość zwracana przez callback jest używana do wypełnienia lub odrzucenia obietnicy. Jeśli jednak oddzwonienie zwróci inną obietnicę, wówczas nowa obietnica (ta, do której zwrócono się wtedy) będzie spełniona tylko wtedy, gdy spełni się ta obietnica. – Bamieh

0

Metoda then zwraca oczekującą obietnicę, która może zostać rozpatrzona asynchronicznie przez wartość zwracaną przez procedurę obsługi wyniku zarejestrowaną w wywołaniu then lub odrzuconą przez zgłoszenie błędu w wywołanym module obsługi.

Dlatego wywołanie AuthUser nie spowoduje nagłego zalogowania użytkownika w synchroniczny sposób, ale zwróci obietnicę, która spowoduje uruchomienie zarejestrowanych procedur obsługi po pomyślnym zalogowaniu (lub niepowodzeniu). Sugerowałbym wyzwolenie całego przetwarzania logowania przez klauzulę o logowaniu na podstawie then. NA PRZYKŁAD. za pomocą nazwanych funkcji podświetl sekwencję przepływu:

let AuthUser = data => { // just the login promise 
    return google.login(data.username, data.password); 
}; 

AuthUser(data).then(processLogin).catch(loginFail); 

function processLogin(token) { 
     // do logged in stuff: 
     // enable, initiate, or do things after login 
} 
function loginFail(err) { 
     console.log("login failed: " + err); 
}