javascript 为什么我的异步函数返回Promise {< pending>}而不是值?

lrl1mhuk  于 2023-03-16  发布在  Java
关注(0)|答案(9)|浏览(217)

我的代码:

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)中获取token到变量中,然后执行一些操作。

5ktev3wc

5ktev3wc1#

只要承诺的结果尚未解决,承诺将始终记录为挂起。无论承诺状态如何(已解决或仍挂起),您都必须对承诺调用.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方法。

详情

根据承诺/A+规范:
承诺解决过程是一个抽象的操作,输入一个承诺和一个值,表示为Resolve(promise,x)。如果x是thenable,它试图使承诺采用x的状态,假设x的行为至少有点像承诺。否则,它用值x实现承诺。
对thenables的这种处理允许promise实现互操作,只要它们公开了Promise/A+兼容的then方法。它还允许Promise/A+实现用合理的then方法“同化”不兼容的实现。
这个规范有点难解析,所以让我们把它分解一下。规则是:
如果.then处理程序中的函数返回一个值,则Promise将使用该值进行解析。如果该处理程序返回另一个Promise,则原始Promise将使用链接Promise的解析值进行解析。下一个.then处理程序将始终包含前一个.then中返回的链接承诺的解析值。
下面将更详细地描述它的实际工作方式:

1. .then函数的返回值将是承诺的解析值。

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"
  });
wpcxdonn

wpcxdonn2#

我遇到了同样的问题,这个问题的答案是自ES2017以来,您可以简单地await函数返回值(截至目前,仅适用于async函数),如:

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

let userToken = await AuthUser(data)
console.log(userToken) // your data
zy1mlcev

zy1mlcev3#

then方法返回一个挂起的承诺,该承诺可以通过在对then的调用中注册的结果处理程序的返回值异步解析,也可以通过在调用的处理程序中引发错误来拒绝。
所以调用AuthUser不会突然让用户同步登录,而是返回一个promise,在登录成功(或失败)后将调用该promise的注册处理程序。我建议通过登录promise的then子句触发所有登录处理。例如,使用命名函数突出显示流程的顺序:

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);
}
sf6xfgos

sf6xfgos4#

如果这种情况发生在像数组这样的多个值上。

[ 
  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

yptwkmov

yptwkmov5#

请参见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()的输入需要是一个以某种方式实际处理令牌的函数。

unftdfkk

unftdfkk6#

您的承诺待定,请在以下时间完成

userToken.then(function(result){
console.log(result)
})

在你剩下的代码之后。所有这些代码所做的就是.then()完成你的承诺&捕获resultvariable中的最终结果&在控制台中打印结果。记住,你不能在全局变量中存储结果。希望这些解释能帮助你。

slwdgvem

slwdgvem7#

我之前也遇到过同样的问题,但我的情况在前端有点不同。我还是会分享我的场景,也许有人会觉得有用。
我有一个API调用/api/user/register在前端与电子邮件,密码和用户名作为请求正文.在提交表单(寄存器形式),则调用一个处理函数,该处理函数启动对/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(...)
     ...
bt1cpqcv

bt1cpqcv8#

试试这个

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 />
gywdnpxw

gywdnpxw9#

我的情况(JS)我忘记添加等待

相关问题