我怎样才能获得承诺的价值?

我正在查看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

我不清楚这是怎么回事。如果我可以对第一个.then()的结果调用.then(),将它们链接起来,我知道我可以,那么promiseB是一个promise对象,类型为Object。它不是Number。那么,“它的价值将是承诺的结果加1”是什么意思呢?

我是否应该访问它为promiseB.value或类似的东西?成功回调如何返回承诺和返回“结果+ 1”?我遗漏了一些东西。

581195 次浏览

promiseAthen函数返回一个新的承诺(promiseB),它在promiseA被解析后立即被解析,它的值是promiseA内成功函数返回的what的值。

在这种情况下,promiseA用值- result解析,然后立即用值result + 1解析promiseB

访问promiseB的值的方法与访问promiseA的结果的方法相同。

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

截至ECMAScript 2016 (ES7, 2016), async/await是JavaScript的标准,这允许使用上述方法的替代语法。现在你可以这样写:

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

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

然而,await只能在async函数中使用。因此,为了稍微缩小,上面的内容必须像这样包含:

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

而且,为了清晰起见,本例中函数doSomething的返回值仍然是一个承诺——因为异步函数返回承诺。因此,如果你想访问返回值,你必须执行result = await doSomething(),这只能在另一个异步函数中执行。基本上,只有在父异步上下文中才能直接访问从子异步上下文中产生的值。

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

这里,promiseA返回一个数字,该数字将作为number参数在promiseB的成功函数中可用。然后会加1。

与你目前的理解略有不同的分析注释可能会有所帮助:

// promiseB will be resolved immediately after promiseA is resolved

这说明promiseB是一个承诺,但它将在promiseA被解决后立即被解决。换句话说,promiseA.then()返回一个赋值给promiseB的promise。

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

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

promiseB.then(function (val) {
// val is now promiseA's result + 1
});

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

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

then方法还返回一个promise: promiseB,它将被解析/拒绝取决于promise的成功/错误处理程序的返回值

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

  1. 不返回→承诺立即解决, 并且undefined被传递给promise eb
  2. 的成功处理程序
  3. 返回值→立即解析promise, 并将该值传递给promiseB
  4. 的成功处理程序
  5. 返回承诺→当承诺被解决时,承诺b将被解决。 当被拒绝时,承诺将被拒绝。传递给 promise的处理程序将是promise
  6. 的结果

有了这样的理解,你就可以理解以下内容:

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

然后调用立即返回promiseB。

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

由于返回值是许诺ea的结果+ 1,成功处理程序返回一个值(上面的选项2),因此许诺eb将立即解析,许诺eb的成功处理程序将被传递许诺ea的结果+ 1。

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
}

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

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

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

pixelbits的回答是正确的,您应该始终使用.then()来访问生产代码中的promise值。

然而,有一种方法可以在promise被解析后直接访问它的值,方法是使用以下不支持的内部node . js绑定:

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

警告:过程。binding从未打算在Node.js核心之外使用,Node.js核心团队正在积极考虑弃用它

我觉得这个例子不言自明。注意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}

node . js REPL中,为了获得一个是promise值的数据库连接,我采用了以下方法:

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

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

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

这让你在运行脚本访问set变量后留在Node.js REPL中。要确认异步函数已经返回,例如,可以记录connection的日志,然后就可以使用该变量了。当然,对于异步函数之外的脚本中的任何代码,人们都不希望依赖于异步函数被解析。

以前有一些不错的答案,下面是ES6箭头函数版本:

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

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

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

await (中数):

await表达式导致异步函数的执行暂停,直到Promise被解决(即,实现或拒绝),并在实现后恢复异步函数的执行。当恢复时,await表达式的值是已实现的Promise的值。

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

中数 web文档中阅读更多关于等待承诺的信息。

在交互提示符下进行实验时,可以通过将值赋给全局变量来访问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

在代码中,这种想法似乎总是强迫人们把“follow up”;编码成&;then()&;部分(或者,等效地,如果我理解了,变成async/await模式,如果我理解了,它被重写成"then()"模式)。我想这个想法是为了防止“阻塞”。这个系统,尽管没有提供后门来同步获取值,但在我看来,它对语言设计者来说太家长式了。

注意,还是从交互式命令行:

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

这是因为代码在&;then()&;没有运行尚未。

然而,在“;下一行”;(在交互提示处)你可以这样做:

> xyz
17

实际上,在交互式(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函数”中做到这一点,但这会让你得到一个承诺,而不是你想要的值:

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

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

Promise.resolve() .resolve(

let promiseB = promiseA;


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

如果你需要查看JSON对象的多个层次:

let promiseB = promiseA;


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