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

发布于 2025-01-17 14:43:07 字数 438 浏览 1 评论 0原文

我的代码:

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

妄司 2025-01-24 14:43:08

只要其结果尚未解决,Promise 将始终记录为待处理。无论 Promise 状态如何(已解决或仍待处理),您都必须对 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 的行为至少有点像
承诺。否则,它会履行值为 x 的承诺。

对 thenable 的这种处理允许 Promise 实现
互操作,只要它们公开 Promises/A+ 兼容的那么
方法。它还允许 Promises/A+ 实现“同化”
使用合理的 then 方法实现不合格的实现。

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

如果 .then 处理程序中的函数返回一个值,则 Promise 将使用该值进行解析。如果处理程序返回另一个 Promise,则原始 Promise 将使用链接的 Promise 的解析值进行解析。下一个 .then 处理程序将始终包含前面的 .then 返回的链式 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.如果 .then 函数返回一个 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"
  });

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

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 Promise is passed to its .then or .catch methods.

Details

According to the Promises/A+ spec:

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.

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

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

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

1. The return of the .then function will be the resolved value of the 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 .then function returns a Promise, then the resolved value of that chained promise is passed to the following .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"
  });
橙幽之幻 2025-01-24 14:43:08

我遇到了同一问题,该问题的答案是自ES2017以来,您可以简单地等待函数返回值(截至目前,仅在async function中起作用) , 喜欢:

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

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

I ran into the same issue and the answer for the problem is since ES2017, that you can simply await the functions return value (as of now, only works in async functions), like:

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

let userToken = await AuthUser(data)
console.log(userToken) // your data
无语# 2025-01-24 14:43:08

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

[ 
  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

If that situation happens for a multiple values like an array.

[ 
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> }
]

You can use Promise.all() this will resolve all promises.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

病毒体 2025-01-24 14:43:08

然后然后方法返回一个未决的承诺,可以通过在调用然后中注册的结果处理程序的返回值来异步解决,或者通过在处理程序中丢弃错误而被拒绝称为。

因此,调用authuser不会突然以同步记录用户,而是返回一个承诺,然后在登录成功(或失败)之后将被调用。我建议通过然后登录承诺的子句触发所有登录处理。例如,使用命名函数突出显示流的顺序:

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

The then method 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.

So calling AuthUser will 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 then clause of the login promise. E.G. using named functions to highlight the sequence of flow:

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);
}
久随 2025-01-24 14:43:08

请参阅 MDN 中有关 Promise 的部分。 特别是,查看 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 =>; { 返回令牌; } 不执行任何操作;相反,您对 then() 的输入需要是一个以某种方式实际处理令牌的函数。

See the MDN section on Promises. In particular, look at the return type of 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.

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

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 AuthUser function should. What AuthUser returns is the result of calling google.login(username, password).then(callback);, which happens to be a Promise.

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.

药祭#氼 2025-01-24 14:43:08

完成

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

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

Your Promise is pending, complete it by

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 result variable & print result in console.
Keep in mind, you cannot store the result in global variable.
Hope that explanation might help you.

野生奥特曼 2025-01-24 14:43:08

我之前也遇到过同样的问题,但我在前端的情况有点不同。无论如何,我会分享我的场景,也许有人会发现它有用。

我在前端对 /api/user/register 进行了 api 调用,使用电子邮件、密码和用户名作为请求正文。提交表单(注册表单)时,将调用一个处理函数,该函数启动对 /api/user/register 的获取调用。我在此处理函数的开头行中使用了 event.preventDefault() ,所有其他行(例如形成请求正文以及 fetch 调用)都是在 event.preventDefault() 之后编写的。这返回了一个待处理的承诺

但是当我将请求正文形成代码放在 event.preventDefault() 之上时,它返回了真正的承诺。像这样:

event.preventDefault();
    const data = {
        'email': email,
        'password': password
    }
    fetch(...)
     ...

而不是:

     const data = {
            'email': email,
            'password': password
        }
     event.preventDefault();
     fetch(...)
     ...

I had the same issue earlier, but my situation was a bit different in the front-end. I'll share my scenario anyway, maybe someone might find it useful.

I had an api call to /api/user/register in the frontend with email, password and username as request body. On submitting the form(register form), a handler function is called which initiates the fetch call to /api/user/register. I used the event.preventDefault() in the beginning line of this handler function, all other lines,like forming the request body as well the fetch call was written after the event.preventDefault(). This returned a pending promise.

But when I put the request body formation code above the event.preventDefault(), it returned the real promise. Like this:

event.preventDefault();
    const data = {
        'email': email,
        'password': password
    }
    fetch(...)
     ...

instead of :

     const data = {
            'email': email,
            'password': password
        }
     event.preventDefault();
     fetch(...)
     ...
泼猴你往哪里跑 2025-01-24 14:43:08

试试这个

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

Try this

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

爱的那么颓废 2025-01-24 14:43:08

我是我的案子(JS),我忘了添加等待

Im my case (JS) I forgot to add await

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文