如何获取承诺的价值?

How can I access the value of a promise?

提问人:temporary_user_name 提问时间:4/8/2015 最后编辑:Peter Mortensentemporary_user_name 更新时间:4/1/2023 访问量:689705

问:

我正在查看 Angular 文档中的这个示例,但我认为这可能适用于一般的承诺。下面的示例是从他们的文档中逐字复制的,并包含他们的注释:$q

promiseB = promiseA.then(function(result) {
  return result + 1;
});

// promiseB will be resolved immediately after promiseA is resolved and its value
// will be the result of promiseA incremented by 1

我不清楚这是如何工作的。如果我可以调用第一个的结果,将它们链接起来,我知道我可以,那么就是一个 promise 对象,类型为 。它不是 .那么,“它的值将是 promiseA 递增 1 的结果”是什么意思呢?.then().then()promiseBObjectNumber

我是否应该访问它或类似的东西?成功回调如何返回 promise 并返回 “result + 1”?我错过了什么。promiseB.value

javascript angularjs angular-promise

评论

0赞 Roland 7/29/2017
我问了一个相关的问题:为什么 Promise 没有 get() 函数?
4赞 Heretic Monkey 2/28/2020
这回答了你的问题吗?如何返回异步调用的响应?

答:

252赞 Nachshon Schwartz 4/8/2015 #1

promiseA的函数返回一个新的 promise(),该 promise 在解析后立即解析,其值是从 success 函数返回的值。thenpromiseBpromiseApromiseA

在这种情况下,使用值进行解析 - 然后立即使用值 进行解析。promiseAresultpromiseBresult + 1

访问 的值与访问 的结果的方式相同。promiseBpromiseA

promiseB.then(function(result) {
    // here you can use the result of promiseB
});

ECMAScript 2016 (ES7, 2016) 开始,/ 是 JavaScript 的标准,它允许使用替代上述方法的语法。您现在可以编写:asyncawait

let result = await functionThatReturnsPromiseA();
result = result + 1;

现在没有 promiseB,因为我们已经使用 解开了 promiseA 的结果,你可以直接使用它。await

但是,只能在函数内部使用。因此,为了稍微缩小,上述内容必须像这样包含:awaitasync

async function doSomething() {
    let result = await functionThatReturnsPromiseA();
    return result + 1;
}

而且,为了清楚起见,此示例中函数的返回值仍然是一个 promise,因为异步函数返回 promise。因此,如果要访问该返回值,则必须执行,这只能在另一个异步函数中执行。基本上,只有在父异步上下文中,才能直接访问从子异步上下文生成的值。doSomethingresult = await doSomething()

评论

4赞 Nachshon Schwartz 4/8/2015
从理论上讲,承诺是他们自己的对象。它们包含一个结果,可以通过 promise 的 success 函数访问该结果。
4赞 temporary_user_name 4/8/2015
因此,如果你想处理一个 promise 的异步回调的返回值,它必须在另一个异步回调中完成。意义。我一直在寻找一种方法来获得一些最终的原始返回值,但我想考虑到上下文,这将违背理性。
2赞 Benjamin Gruenbaum 4/9/2015
@Aerovistae实际上,ES6 引入了使这成为可能的生成器,而 ES7 引入了异步函数——这两者都给了你语法糖,而不是让它看起来像同步代码的承诺(通过在后台运行状态机)——所以请保持:)
1赞 EternalObserver 11/1/2021
立即解决答案的第一行是什么意思?
3赞 Suncat2000 6/14/2022
在异步函数中包装 promise 仍然是异步的。如何才能立即获得已解决的承诺的结果?
5赞 harishr 4/8/2015 #2

promiseB 的函数接收从 promiseA 的函数返回的内容。.then.then

这里 promiseA 返回一个数字,该数字将作为 promiseB 成功函数中的参数提供。然后将递增 1。number

4赞 Jason Cust 4/8/2015 #3

以与您当前理解略有不同的方式解析评论可能会有所帮助:

// promiseB will be resolved immediately after promiseA is resolved

这说明这是一个承诺,但在解决后将立即解决。另一种看待此方式意味着返回分配给 的 promise 。promiseBpromiseApromiseA.then()promiseB

// and its value will be the result of promiseA incremented by 1

这意味着解析到的值是将作为其 successCallback 值接收的值:promiseApromiseB

promiseB.then(function (val) {
  // val is now promiseA's result + 1
});
37赞 Michael Kang 4/8/2015 #4

当一个 promise 被解析/拒绝时,它将调用其成功/错误处理程序:

var promiseB = promiseA.then(function(result) {
   // do something with result
});

该方法还返回一个 promise:promiseB,它将根据 promiseA 的成功/错误处理程序的返回值进行解析/拒绝。then

promiseA 的成功/错误处理程序可以返回三个可能的值,这些值将影响 promiseB 的结果:

  1. 立即解决 PromiseB →不返回任何内容, 和 undefined 传递给 promiseB 的成功处理程序
  2. 返回一个值→立即解析 PromiseB, 并将该值传递给 promiseB 的成功处理程序
  3. 返回一个 promise → 解析后,promiseB 将被解析。 当被拒绝时,promiseB 将被拒绝。传递给的值 promiseB 的 then 处理程序将是 promise 的结果

有了这种理解,你就可以理解以下几点:

promiseB = promiseA.then(function(result) {
  return result + 1;
});

then 调用立即返回 promiseB。

当 promiseA 被解析时,它会将结果传递给 promiseA 的成功处理程序。

由于返回值是 promiseA 的结果 + 1,因此成功处理程序返回一个值(上面的选项 2),因此 promiseB 将立即解析,并且 promiseB 的成功处理程序将传递给 promiseA 的结果 + 1。

-2赞 tomnyson 6/14/2018 #5
promiseA(pram).then(
     result => { 
     //make sure promiseA function allready success and response
     //do something here
}).catch(err => console.log(err)) => {
     // handle error with try catch
}

评论

4赞 Alexander 6/18/2018
虽然此代码可以回答问题,但提供有关它如何以及为何解决问题的其他上下文将提高答案的长期价值。
-4赞 OxFEEDFACE 7/28/2018 #6

您可以使用 JavaScript 中的异步等待方法轻松做到这一点。

下面是一个使用超时检索 WebRTC promise 值的示例。

function await_getipv4(timeout = 1000) {
    var t1 = new Date();
    while(!window.ipv4) {
        var stop = new Date() - t1 >= timeout;
        if(stop) {
            console.error('timeout exceeded for await_getipv4.');
            return false;
        }
    }
    return window.ipv4;
}

function async_getipv4() {
    var ipv4 = null;
    var findIP = new Promise(r=>{var w=window,a=new (w.RTCPeerConnection||w.mozRTCPeerConnection||w.webkitRTCPeerConnection)({iceServers:[]}),b=()=>{};a.createDataChannel("");a.createOffer(c=>a.setLocalDescription(c,b,b),b);a.onicecandidate=c=>{try{c.candidate.candidate.match(/([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g).forEach(r)}catch(e){}}})
    findIP.then(ip => window.ipv4 = ip);
    return await_getipv4();
};

评论

0赞 OxFEEDFACE 7/28/2018
重要的是不要在这里运行这个片段,而是在真正的浏览器中运行,我相信这是由于沙盒造成的。
0赞 Liam 3/6/2021
这将阻塞主线程,直到异步返回,首先破坏了使用承诺的对象,不要这样做......
0赞 Peter Mortensen 9/29/2022
相关:如果代码不需要代码段功能,我们是否应该帮助新用户编写代码段?
8赞 Zeus Lalkaka 1/4/2019 #7

Pixelbits的答案是正确的,你应该始终使用在生产代码中访问承诺的价值。.then()

但是,有一种方法可以在解析 promise 的值后直接访问该值,方法是使用以下不受支持的内部 Node.js 绑定:

process.binding('util').getPromiseDetails(myPromise)[1]

警告:process.binding 从未打算在 Node.js 核心之外使用,Node.js 核心团队正在积极寻求弃用它

评论

1赞 mteam88 8/9/2022
找到一个不应该使用的答案是不寻常的(:
-2赞 Master James 1/16/2019 #8

我觉得这个例子是不言自明的。请注意,await 是如何等待结果的,因此您错过了返回的 Promise。

cryA = crypto.subtle.generateKey({name:'ECDH', namedCurve:'P-384'}, true, ["deriveKey", "deriveBits"])
Promise {<pending>}
cryB = await crypto.subtle.generateKey({name:'ECDH', namedCurve:'P-384'}, true, ["deriveKey", "deriveBits"])
{publicKey: CryptoKey, privateKey: CryptoKey}

评论

2赞 Samed 4/10/2019
这必须在异步函数中。
1赞 dmstack 8/2/2019 #9

Node.js REPL 中,为了获取作为 promise 值的数据库连接,我采用了以下方法:

let connection
try {
  (async () => {
    connection = await returnsAPromiseResolvingToConnection()
  })()
} catch(err) {
  console.log(err)
}

with 行通常会返回一个 promise。此代码可以粘贴到 Node.js REPL 中,也可以保存在 index.js 中。它可以在 Bash 中运行await

node -i -e "$(< index.js)"

在运行脚本后,您将留在 Node.js REPL 中,并有权访问设置变量。例如,若要确认异步函数已返回,可以进行日志记录,然后即可使用该变量。当然,对于异步函数之外的脚本中的任何代码,人们还不想指望异步函数正在解析。connection

评论

0赞 E.E.33 5/24/2021
这是颤音。非常合法。也适用于 ts-node。
6赞 roopa l 12/19/2019 #10

之前有一些很好的答案,这里是 ES6 箭头函数版本:

var something = async() => {
    let result = await functionThatReturnsPromiseA();
    return result + 1;
}

评论

1赞 Suncat2000 5/15/2022
最后,如何获得承诺价值的答案!谢谢!
0赞 Suncat2000 5/16/2022
现在我们可以定义一个通用的匿名函数来解开该值。我从相关答案中得到了诀窍,因此 TypeScript 将 T 视为泛型并知道“绝对类型化”的值。返回的 promise 已实现(已解决或已拒绝),并且可以立即链接以使用该值。.<T extends unknown>.then()const getPromiseValue = async <T extends unknown> (p: Promise<T>) => await p;
9赞 Setop 8/25/2022
但 then 是一个异步函数。当计算 () 时,结果是一个 所以我们循环...sometingsomething()Promise
3赞 LT-Sites 6/12/2020 #11

我对 JavaScript 承诺的学习速度很慢。默认情况下,所有异步函数都返回一个 promise,您可以将结果包装为:

(async () => {
//Optional "await"
  await yourAsyncFunctionOrPromise()
    .then(function (result) {
      return result +1;
    })
    .catch(function (error) {
      return error;
    })()
})

awaitMDN):

await 表达式使异步函数执行暂停,直到 Promise 结算(即已履行或已拒绝),并在履行后恢复异步函数的执行。恢复时,await 表达式的值是已实现的 Promise 的值。

如果 Promise 被拒绝,await 表达式将抛出被拒绝的值

MDN Web 文档中阅读有关 awaitpromise 的更多信息。

0赞 Michael Albert 11/28/2021 #12

在交互式提示符下进行实验时,可以通过将值分配给 “then()” 函数中的全局变量来访问 Promise 的值,例如:

> promise = new Promise((resolve, reject) => resolve(17));
Promise {
   17,
   [Symbol(async_id_symbol)]: 7600,
   [Symbol(trigger_async_id_symbol)]: 5,
   [Symbol(destroyed)]: { destroyed: false }
}
> global_cheat = null;
null
> promise.then((v) => { global_cheat = v; } );
Promise {
   <pending>,
  [Symbol(async_id_symbol)]: 7875,
  [Symbol(trigger_async_id_symbol)]: 7600,
  [Symbol(destroyed)]: { destroyed: false }
}
> global_cheat
17

在代码中,这个想法似乎是总是强制人们将“后续”代码放入“then()”部分(或者,如果我理解的话,相当于将 async/await 模式放入,如果我理解,它也会被重写为“then()”模式)。我想这个想法是可以防止“阻塞”系统,尽管在我看来,没有提供后门来同步获取价值似乎是语言设计者的过度家长式作风。

请注意,再次从交互式命令行:

> xyz=null; promise.then((v) => {xyz = v;}); console.log(`xyz=${xyz}`);
xyz=null

这是因为“then()”中的代码尚未运行。

但是,在“下一行”(在交互式提示符下)可以执行以下操作:

> xyz
17
3赞 Michael Albert 11/28/2021 #13

实际上,从交互式(Node.js)提示中,可以“等待”:

> y = new Promise((resolve, reject) => resolve(23));
Promise {
   23,
   [Symbol(async_id_symbol)]: 10419,
   [Symbol(trigger_async_id_symbol)]: 5,
   [Symbol(destroyed)]: { destroyed: false }
}
> v = await y;
23

这在 REPL 进行实验时很有用。

你不能在“普通”函数中这样做:

> function foo() { let z = await y; return z; }
Uncaught SyntaxError:
Unexpected token 'y'

你可以在“异步函数”中执行此操作,但这会让你背负着一个承诺,而不是你想要的值:

> async function foo() { let z = await y; return z; }
undefined
> foo()
Promise {
  <pending>,
  [Symbol(async_id_symbol)]: 10571,
  [Symbol(trigger_async_id_symbol)]: 5,
  [Symbol(destroyed)]: { destroyed: false }
}

评论

0赞 Suncat2000 5/16/2022
但是使用 async-await 函数,至少您知道该值立即可用,并且可以在返回的 promise 的子句中使用。.then()
-1赞 datalifenyc 8/22/2022 #14

MDN文档帮助我解决了这个问题:

Promise.resolve()

let promiseB = promiseA;

promiseB.then((value) => {
    console.log(value);
});

如果需要对 JSON 对象进行多个级别的访问:

let promiseB = promiseA;

promiseB.then((value) => {
    console.log(value?.key1.key2);
});