我的代码:
let AuthUser = data => {
return google.login(data.username, data.password).then(token => { return token } )
}
当我尝试运行这样的东西时:
let userToken = AuthUser(data)
console.log(userToken)
我越来越:
Promise { <pending> }
但为什么?
我的主要目标是从返回承诺的 google.login(data.username, data.password)
获取令牌到变量中。然后才执行一些操作。
getFirstUser
函数
只要其结果尚未解决,promise 将始终记录未决。无论承诺状态如何(已解决或仍待处理),您都必须在承诺上调用 .then
以捕获结果:
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"
})
这是为什么?
承诺只是向前的方向;您只能解决它们一次。 Promise
的解析值被传递给它的 .then
或 .catch
方法。
细节
根据 Promises/A+ 规范:
承诺解决过程是一个抽象操作,将承诺和值作为输入,我们将其表示为 [[Resolve]](promise, x)。如果 x 是 thenable,它会尝试让 Promise 采用 x 的状态,假设 x 的行为至少有点像 Promise。否则,它以值 x 履行承诺。对 thenables 的这种处理允许 Promise 实现互操作,只要它们公开一个符合 Promises/A+ 的 then 方法。它还允许 Promises/A+ 实现使用合理的 then 方法“吸收”不符合要求的实现。
这个规范有点难解析,所以让我们分解一下。规则是:
如果 .then
处理程序中的函数返回一个值,则 Promise
使用该值解析。如果处理程序返回另一个 Promise
,则原始 Promise
将使用链式 Promise
的解析值解析。下一个 .then
处理程序将始终包含在前一个 .then
中返回的链式承诺的解析值。
下面更详细地描述了它的实际工作方式:
<强> 1。 .then
函数的返回值将是 promise 的解析值。
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。如果 .then
函数返回 Promise
,则该链式承诺的解析值将传递给以下 .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"
});
我知道这个问题是 2 年前提出的,但我遇到了同样的问题,问题的答案是从 ES2017 开始,您可以简单地 await
函数返回值(截至目前,仅适用于 async
函数), 喜欢:
let AuthUser = function(data) {
return google.login(data.username, data.password)
}
let userToken = await AuthUser(data)
console.log(userToken) // your data
.then(token => return token)
,这只是一个不必要的传递。只需返回 google 登录调用。
await
,则会引发错误。也许这里更好的例子是使 AuthUser
函数 async
,然后以 return await google.login(...);
结束
then
方法返回一个待处理的 Promise,它可以通过在对 then
的调用中注册的结果处理程序的返回值异步解决,或者通过在被调用的处理程序中抛出一个错误来拒绝。
因此调用 AuthUser
不会突然同步登录用户,而是返回一个承诺,然后注册的处理程序将在登录成功(或失败)后被调用。我建议通过登录承诺的 then
子句触发所有登录处理。 EG 使用命名函数来突出显示流程的顺序:
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);
}
如果这种情况发生在像数组这样的多个值上。
[
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
Promise { <pending> }
]
您可以使用 Promise.all()
这将解决所有承诺。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
请参阅有关 Promises. 的 MDN 部分,特别是查看 then(). 的返回类型
要登录,用户代理必须向服务器提交请求并等待接收响应。由于在请求往返期间使您的应用程序完全停止执行通常会导致糟糕的用户体验,因此实际上每个登录您(或执行任何其他形式的服务器交互)的 JS 函数都将使用 Promise,或者非常类似的东西, 以异步方式传递结果。
现在,还要注意 return
语句总是在它们出现的函数的上下文中进行评估。所以当你写的时候:
let AuthUser = data => {
return google
.login(data.username, data.password)
.then( token => {
return token;
});
};
语句 return token;
意味着传递给 then()
的匿名函数应该返回令牌,而不是 AuthUser
函数应该返回。 AuthUser
返回的是调用 google.login(username, password).then(callback);
的结果,这恰好是一个 Promise。
最终你的回调 token => { return token; }
什么都不做;相反,您对 then()
的输入需要是一个以某种方式实际处理令牌的函数。
return
,在这种情况下 - 好吧,我强烈反对,但错误仍然是我的,我为它。
token => { return token; }
什么都不做 而不是声称它会适得其反。您可以一直说 google.login(username, password).then(token=>{return token;}).then(token=>{return token;})
等等,但您只能返回一个使用令牌解析的 Promise
— 就像您刚刚将其保留为 google.login(username, password);
一样。我不确定你为什么觉得这是“非常错误的”。
return token
不能像 OP 预期的那样工作。
promise.then(result => { return result; })
完全等同于 promise
,因此方法调用 什么都不做 并且应该删除以简化代码并增强可读性 - a完全正确的说法。
您的 Promise 待处理,请通过以下方式完成
userToken.then(function(result){
console.log(result)
})
在您剩余的代码之后。这段代码所做的只是让 .then()
完成了您的承诺 &在 result 变量中捕获最终结果 &在控制台中打印结果。请记住,您不能将结果存储在全局变量中。希望解释可以帮助你。
我之前也遇到过同样的问题,但是我在前端的情况有点不同。无论如何,我会分享我的场景,也许有人会觉得它有用。
我在前端使用电子邮件、密码和用户名作为请求正文对 /api/user/register
进行了 api 调用。在提交表单(注册表单)时,会调用一个处理函数,该函数会启动对 /api/user/register
的提取调用。我在此处理函数的开头行中使用了 event.preventDefault()
,所有其他行,例如形成请求主体以及 fetch 调用都是在 event.preventDefault()
之后编写的。这返回了一个 pending promise
。
但是当我将请求体形成代码放在 event.preventDefault()
之上时,它返回了真正的承诺。像这样:
event.preventDefault();
const data = {
'email': email,
'password': password
}
fetch(...)
...
代替 :
const data = {
'email': email,
'password': password
}
event.preventDefault();
fetch(...)
...
尝试这个
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: " + 结果 }); } });异步函数 asyncTest(a, b) { return await (a + b); };
不定期副业成功案例分享
Uncaught SyntaxError: Unexpected token .
。第二个需要返回Promise
.then
。更新了答案