Mijn code:
let AuthUser = data => {
return google.login(data.username, data.password).then(token => { return token } )
}
En wanneer ik iets als dit probeer uit te voeren:
let userToken = AuthUser(data)
console.log(userToken)
Ik krijg:
Promise { <pending> }
Maar waarom?
Mijn hoofddoel is om Token te krijgen van google.login(data.username, data.password)
die een belofte retourneert, in een variabele. En alleen en vervolgens enkele acties voorvorm.
1, Autoriteit 100%
De belofte zal altijd in behandeling zijn zolang de resultaten nog niet zijn opgelost. U moet .then
beloven met de belofte om de resultaten vast te leggen, ongeacht de belofte (opgelost of nog in behandeling):
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) // "Some User token"
})
Waarom is dat?
Beloften zijn alleen voorwaartse richting; Je kunt ze maar één keer oplossen. De opgeloste waarde van een Promise
wordt doorgegeven aan de .then
of .catch
methoden.
Details
Volgens de beloften / A + Spec:
De procedure voor belofingsresolutie is een abstracte operatie die neemt als
voer een belofte en een waarde in, die we aanduiden als [[Resolve]](promise,
x). Als x een dan is, probeert het de belofte de toestand van te laten aannemen
x, in de veronderstelling dat x zich op zijn minst enigszins als a . gedraagt
belofte. Anders voldoet het aan de belofte met de waarde x.Deze behandeling van danables stelt belofte-implementaties in staat om
interoperabel zijn, zolang ze een Promises/A+-compliant dan blootleggen
methode. Het stelt Promises/A+ implementaties ook in staat om te “assimileren”
niet-conforme implementaties met redelijke methoden.
Deze specificatie is een beetje moeilijk te ontleden, dus laten we het opsplitsen. De regel is:
Als de functie in de .then
-handler een waarde retourneert, wordt de Promise
opgelost met die waarde. Als de handler nog een Promise
retourneert, wordt de oorspronkelijke Promise
opgelost met de opgeloste waarde van de gekoppelde Promise
. De volgende .then
-handler bevat altijd de opgeloste waarde van de geketende belofte die is geretourneerd in de vorige .then
.
De manier waarop het echt werkt, wordt hieronder in meer detail beschreven:
1. De terugkeer van de functie .then
is de opgeloste waarde van de belofte.
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. Als de functie .then
een Promise
retourneert, wordt de opgeloste waarde van die geketende belofte doorgegeven aan de volgende .then
.
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"
});
Antwoord 2, autoriteit 13%
Ik weet dat deze vraag 2 jaar geleden is gesteld, maar ik loop tegen hetzelfde probleem aan en het antwoord op het probleem is sinds ES2017, dat je gewoon kunt await
op de retourwaarde van de functie (vanaf nu , werkt alleen in async
-functies), zoals:
let AuthUser = function(data) {
return google.login(data.username, data.password).then(token => { return token } )
}
let userToken = await AuthUser(data)
console.log(userToken) // your data
Antwoord 3, autoriteit 2%
De methode then
retourneert een in behandeling zijnde belofte die asynchroon kan worden opgelost door de retourwaarde van een resultaat-handler die is geregistreerd in de aanroep naar then
, of kan worden afgewezen door een fout te genereren binnen de handler aangeroepen.
Dus het aanroepen van AuthUser
zal de gebruiker niet plotseling synchroon aanmelden, maar een belofte teruggeven waarvan de geregistreerde handlers zullen worden aangeroepen nadat het inloggen is gelukt (of mislukt). Ik zou willen voorstellen om alle login-verwerking te activeren door een then
-clausule van de login-belofte. E.G. benoemde functies gebruiken om de volgorde van de stroom te markeren:
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);
}
4
Zie de MDN-sectie op beloftes. Bekijk in het bijzonder het retourtype dan ().
Om in te loggen, moet de gebruikersagent een verzoek aan de server indienen en wachten om een reactie te ontvangen. Aangezien het de uitvoering van uw aanvraag volledig stoppen tijdens een aanvraag Round-trip meestal zorgt voor een slechte gebruikerservaring, praktisch elke JS-functie die u inlogt (of voert een andere vorm van serverinteractie), een belofte, of iets dergelijks , om resultaten asynchroon te leveren.
Nu, merk ook op dat return
uitspraken altijd worden geëvalueerd in de context van de functie die ze verschijnen. Dus wanneer u schreef:
let AuthUser = data => {
return google
.login(data.username, data.password)
.then( token => {
return token;
});
};
De verklaring return token;
betekende dat de anonieme functie wordt ingevoerd in then()
moet retourneren, niet dat de AuthUser
functie zou moeten. Wat AuthUser
Retourneren is het resultaat van het bellen google.login(username, password).then(callback);
, die toevallig een belofte is.
Uiteindelijk uw terugbellen token => { return token; }
doet niets; In plaats daarvan moet uw invoer naar then()
een functie zijn die het token op de een of andere manier behandelt.
5
Als die situatie gebeurt voor een meerdere waarden zoals een array.
[
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
Promise { <pending> }
]
U kunt Promise.all()
Hiermee wordt alle beloften opgelost.
6
Ik had eerder hetzelfde probleem, maar mijn situatie was een beetje anders in de front-end. Ik zal het sowieso mijn scenario delen, misschien kan iemand het nuttig vinden.
Ik had een api-aanroep naar /api/user/register
in de frontend met e-mail, wachtwoord en gebruikersnaam als verzoektekst. Bij het indienen van het formulier (registerformulier), wordt een handlerfunctie aangeroepen die de ophaalaanroep naar /api/user/register
initieert. Ik gebruikte de event.preventDefault()
in de beginregel van deze handlerfunctie, alle andere regels, zoals het vormen van de request-body en de fetch-aanroep werd geschreven na de event.preventDefault()
. Dit leverde een pending promise
op.
Maar toen ik de code voor het opmaken van de aanvraagtekst boven de event.preventDefault()
plaatste, gaf het de echte belofte terug. Zoals dit:
event.preventDefault();
const data = {
'email': email,
'password': password
}
fetch(...)
...
in plaats van:
const data = {
'email': email,
'password': password
}
event.preventDefault();
fetch(...)
...
Antwoord 7
Probeer dit
var number1 = document.getElementById("number1");
var number2 = document.getElementById("number2");
startAsync.addEventListener("click", function() {
if (number1.value > 0 && number2.value > 0) {
asyncTest(parseInt(number1.value), parseInt(number2.value)).then(function(result) {
document.getElementById("promiseResolved").textContent = "promiseResolved: " + result
});
} else {
asyncTest(1, 2).then(function(result) {
document.getElementById("promiseResolved").textContent = "promiseResolved: " + result
});
}
});
async function asyncTest(a, b) {
return await (a + b);
};
<button id="startAsync">start Async function</button><br />
<input type="number" id="number1" /><br />
<input type="number" id="number2" /><br />
<span id="promiseResolved"></span><br />