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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38884522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 21:59:44  来源:igfitidea点击:

Why is my asynchronous function returning Promise { <pending> } instead of a value?

javascriptnode.jspromise

提问by Src

My code:

我的代码:

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

And when i try to run something like this:

当我尝试运行这样的东西时:

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

I'm getting:

我越来越:

Promise { <pending> }

But why?

但为什么?

My main goal is to get token from google.login(data.username, data.password)which returns a promise, into a variable. And only then preform some actions.

我的主要目标是将google.login(data.username, data.password)返回承诺的令牌获取到变量中。然后才执行一些操作。

回答by Bamieh

The promise will always log pending as long as its results are not resolved yet. You must call .thenon the promise to capture the results regardless of the promise state (resolved or still pending):

只要其结果尚未解决,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"
})

Why is that?

这是为什么?

Promises are forward direction only; You can only resolve them once. The resolved value of a Promiseis passed to its .thenor .catchmethods.

Promises 只是向前的;您只能解决一次。a 的解析值Promise传递给它的.then.catch方法。

Details

细节

According to the Promises/A+ spec:

根据 Promises/A+ 规范:

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.

承诺解析过程是一个抽象操作,将承诺和值作为输入,我们将其表示为 [[Resolve]](promise, x)。如果 x 是一个 thenable,它会尝试让 promise 采用 x 的状态,假设 x 的行为至少有点像 promise。否则,它以值 x 履行承诺。

对 thenables 的这种处理允许 promise 实现互操作,只要它们公开一个符合 Promises/A+ 的 then 方法。它还允许 Promises/A+ 实现使用合理的 then 方法“同化”不一致的实现。

This spec is a little hard to parse, so let's break it down. The rule is:

这个规范有点难以解析,所以让我们分解一下。规则是:

If the function in the .thenhandler returns a value, then the Promiseresolves with that value. If the handler returns another Promise, then the original Promiseresolves with the resolved value of the chained Promise. The next .thenhandler will always contain the resolved value of the chained promise returned in the preceding .then.

如果.then处理程序中的函数返回一个值,则Promise使用该值进行解析。如果处理程序返回另一个Promise,则原始处理程序Promise使用链式 的已解析值进行解析Promise。下一个.then处理程序将始终包含前一个 中返回的链式承诺的解析值.then

The way it actually works is described below in more detail:

下面更详细地描述了它的实际工作方式:

1. The return of the .thenfunction will be the resolved value of the promise.

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. If the .thenfunction returns a Promise, then the resolved value of that chained promise is passed to the following .then.

2. 如果.then函数返回 a Promise,则该链式 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"
  });

回答by Marius Seack

I know this question was asked 2 years ago, but I run into the same issue and the answer for the problem is since ES6, that you can simply awaitthe functions return value, like:

我知道这个问题是 2 年前提出的,但我遇到了同样的问题,问题的答案是从 ES6 开始,你可以简单地await函数返回值,例如:

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

回答by traktor53

The thenmethod returns a pending promise which can be resolved asynchronously by the return value of a result handler registered in the call to then, or rejected by throwing an error inside the handler called.

then方法返回一个挂起的承诺,它可以通过调用中注册的结果处理程序的返回值异步解析then,或者通过在调用的处理程序中抛出错误来拒绝。

So calling AuthUserwill not suddenly log the user in synchronously, but returns a promise whose then registered handlers will be called after the login succeeds ( or fails). I would suggest triggering all login processing by a thenclause of the login promise. E.G. using named functions to highlight the sequence of flow:

因此,调用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);
}

回答by Jesse Amano

See the MDN section on Promises.In particular, look at the return type of then().

请参阅关于Promises的 MDN 部分特别要注意then()的返回类型

To log in, the user-agent has to submit a request to the server and wait to receive a response. Since making your application totally stop execution during a request round-trip usually makes for a bad user experience, practically every JS function that logs you in (or performs any other form of server interaction) will use a Promise, or something very much like it, to deliver results asynchronously.

要登录,用户代理必须向服务器提交请求并等待接收响应。由于在请求往返期间使您的应用程序完全停止执行通常会导致糟糕的用户体验,因此几乎每个登录您(或执行任何其他形式的服务器交互)的 JS 函数都会使用 Promise 或非常类似的东西, 异步传递结果。

Now, also notice that returnstatements are always evaluated in the context of the function they appear in. So when you wrote:

现在,还要注意return语句总是在它们出现的函数的上下文中进行评估。所以当你写:

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

the statement return token;meant that the anonymous function being passed into then()should return the token, not that the AuthUserfunction should. What AuthUserreturns is the result of calling google.login(username, password).then(callback);, which happens to be a Promise.

该语句return token;意味着被传入的匿名函数then()应该返回令牌,而不是AuthUser函数应该返回。什么AuthUser返回与调用的结果google.login(username, password).then(callback);,这恰好是一个承诺。

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.

最终你的回调token => { return token; }什么都不做;相反,您的输入then()需要是一个以某种方式实际处理令牌的函数。

回答by Naveen Nirban Yadav

Your Promiseis pending, complete it by

您的Promise正在等待中,请通过以下方式完成

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

after your remaining code. All this code does is that .then()completes your promise & captures the end result in resultvariable & print result in console. Keep in mind, you cannot store the result in global variable. Hope that explanation might help you.

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