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

koaltpgm  于 2021-09-23  发布在  Java
关注(0)|答案(8)|浏览(359)

我的代码:

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) 它将一个承诺返回到一个变量中。只有这样才能实施一些行动。

e3bfsja2

e3bfsja21#

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

[ 
  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

vohkndzv

vohkndzv2#

您的承诺尚未兑现,请提前完成

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

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

lsmd5eda

lsmd5eda3#

我之前也有同样的问题,但我在前端的情况有点不同。我将分享我的场景,也许有人会觉得它有用。
我有一个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(...)
     ...
zpf6vheq

zpf6vheq4#

试试这个

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

eanckbw95#

只要其结果尚未解决,承诺将始终记录挂起。你必须打电话 .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"
})

为什么呢?
承诺只是前进的方向;您只能解决它们一次。a的解析值 Promise 传递给其 .then.catch 方法。

细节

根据承诺/a+规范:
承诺解析过程是以承诺和值作为输入的抽象操作,我们将其表示为resolve(承诺,x)。如果x是一个表,那么它试图使promise采用x的状态,假设x的行为至少有点像promise。否则,它将以x值履行承诺。
这种对表的处理允许promise实现进行互操作,只要它们公开符合promises/a+的then方法。它还允许promises/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"
  });
9rygscc1

9rygscc16#

我知道这个问题是两年前提出的,但我遇到了同样的问题,问题的答案是从es2017开始,你可以 await 函数返回值(到目前为止,仅在 async 功能),例如:

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
42fyovps

42fyovps7#

这个 then 方法返回一个挂起的承诺,该承诺可以通过调用中注册的结果处理程序的返回值异步解析 then ,或通过在调用的处理程序中抛出错误而被拒绝。
这么叫 AuthUser 不会突然同步登录用户,但会返回一个承诺,在登录成功(或失败)后将调用其随后注册的处理程序。我建议通过 then 登录承诺的条款。e、 g.使用命名函数突出显示流的顺序:

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

prdp8dxp8#

请参阅mdn中有关承诺的部分。特别是,请查看then()的返回类型。
要登录,用户代理必须向服务器提交请求并等待接收响应。由于在请求往返过程中让应用程序完全停止执行通常会导致糟糕的用户体验,因此实际上,让您登录(或执行任何其他形式的服务器交互)的每个js函数都会使用承诺或类似的东西来异步交付结果。
现在,还要注意 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); ,这正好是一个承诺。
最终你的回电 token => { return token; } 什么也不做;相反,您的输入 then() 必须是以某种方式实际处理令牌的函数。

相关问题