JavaScript中的双括号表示什么,如何访问它们?

80

情况

我有下面这个使用Promise的函数。

var getDefinitions = function() {
    return new Promise(function(resolve) {
        resolve(ContactManager.request("definition:entities"));
    });
}

var definitions = getDefinitions()

definitions 的内容是:

Promise {
    [[PromiseStatus]]: "resolved",
    [[PromiseValue]]: child
}

直接访问PromiseValue属性会返回undefined

var value = definitions.PromiseValue; // undefined

问题

双方括号[[ ]]的意思是什么,如何检索[[PromiseValue]]的值。


2
知道你使用的库会有所帮助。 - JJJ
5
我想我正在使用Chrome自带的JavaScript库(??)。 - Jeff
2
看起来这只是承诺状态的描述方式。您可以在Chrome控制台中尝试此操作:new Promise(function(){})。 Chrome的[[PromiseStatus]]可以与Firefox的<state>进行比较。我不太明白问题在哪里(前提是OP知道什么是promise)。 - Denys Séguret
1
据我所知,这只是Chrome向您显示Promise状态的方式。这些属性故意不可在对象外部看到。如果您在Firefox中查看Promise对象,则不会以此方式呈现。我认为这可能只是一种诊断辅助工具。 - Pointy
1
ContactManager.request("definition:entities") 是什么? - Benjamin Gruenbaum
显示剩余13条评论
7个回答

108

双方括号[[ ]]里面是什么?

我的问题是双方括号[[ ]]代表什么,如何检索[[PromiseValue]]的值。

这是一个内部属性。您无法直接访问它。本机承诺只能在then中使用承诺或异步地解包 - 请参见如何从异步调用中返回响应。引用规范:

它们纯粹是为了说明目的而由该规范定义的。ECMAScript的实现必须像在此处描述的方式一样生成和操作内部属性。内部属性的名称用双方括号 [[ ]] 括起来。当算法使用对象的内部属性并且对象未实现指定的内部属性时,将抛出TypeError异常。

您不能

真的 - 它们是什么?

非常好!正如上面的引用所说,它们只是在规范中使用 - 因此它们没有出现在您的控制台中的任何理由。

请保密,但这些是真正的私有符号。它们存在的原因是为了让其他内部方法能够访问[[PromiseValue]]。例如,当io.js决定返回承诺而不是使用回调时,这将使它们能够在确保情况下快速访问这些属性。它们不会暴露给外部。

我能访问它们吗?

除非你自己制作Chrome或V8构建版本,否则无法访问。也许在ES7中可以使用访问修饰符。但目前为止,由于它们不是规范的一部分并且在不同浏览器之间可能无法兼容,因此没有办法 - 抱歉。

那么我该如何获取我的值?

getDefinitions().then(function(defs){
    //access them here
});

但是如果出现错误怎么办?为了防止这种情况,将以下内容添加到您的 .then() 结尾(并且在外部)。

.catch(function(defs){
    //access them here
});

尽管我只是猜测,但我认为您没有正确地转换API,因为这种转换仅适用于同步方法(在这种情况下,请不要返回Promise),或者它已经返回Promise并且已解决(这意味着您根本不需要进行转换 - 只需return即可)。

此外,应该说,在then之外访问Promise的包装值完全违背了Promise的目的。Promise的目的是抽象出非阻塞函数缺失返回值的情况,即Promise代表一个“未来值”。一旦暴露了这个“未来值”(在then之外),整个计算过程中的这些抽象将立即丢失。 - user6445533
如果 Promise 被拒绝,那么这些值将通过 .catch((values) => {}) 而不是 .then(() => {}) 可用。 - jony89
@Benjamin,你是不是指内部插槽和内部方法是由JS引擎根据规范实现的?我读到一个答案,说它们只是词语,没有实现。(也许我在这里误解了)此外,我并不是在询问Promise的上下文,因为我现在对它没有太多的了解。只是一般性地询问像[[PUT]] [[Prototype]]等。 - Number945
一般来说,开发工具中的[[PromiseValue]]实际上是由开发工具生成的 - 当您在控制台上按Enter键时,它会执行一个evaluateOnCallFrame命令,将消息发送到V8,然后返回一个subtype为promise的RemoteObject。这需要显式的即兴支持才能正常工作。以上回答是正确的(这是检查器获取这些属性的位置)但不准确(它们到达那里的方式并不是如此 - 它们是通过显式调试器支持到达的)。 - Benjamin Gruenbaum

18
我今天也遇到了这个问题,并偶然找到了解决方案。
我的解决方案如下:
fetch('http://localhost:3000/hello')
.then(dataWrappedByPromise => dataWrappedByPromise.json())
.then(data => {
    // you can access your data here
    console.log(data)
})

这里,dataWrappedByPromise 是一个 Promise 实例。为了访问 Promise 实例中的数据,我发现只需要使用 .json() 方法来取消包装该实例即可。

希望这有所帮助!


由于柯里化,then(dataWrappedByPromise => dataWrappedByPromise.json()) 等同于 then(resp.json()) - jymbob
@jymbob,我无法理解你的评论。你说在cafemike定义箭头函数的地方,该定义可以被常量替换;具体来说,你说他的“then()”等同于“then(resp.json())”。首先,“resp”从哪里来?更重要的是,参数“resp.json()”会立即执行,因此在promise仍未解决时传递给“.then()”的参数是执行时产生的任何常量(字符串、对象或数字)。也许你不明白“.then()”期望其参数为函数。 - IAM_AL_X
@IAM_AL_X 呃,我也看不懂我的评论。两年后我唯一能想到的是我本来想提到“console.log”这一行,但打错了。.then(data => { console.log(data)}) 可以简化为 .then(console.log),但你说得对,需要该函数才能访问该函数上的常量。对于任何困惑,我感到抱歉。 - jymbob

5

这个示例是使用React实现的,但大部分情况下都应该是相同的。

你自己的URL替换this.props.url以获取大多数其他框架的工作效果。

解析res.json()返回[[promiseValue]],但如果你将其返回到下面的另一个.then()方法中,则可以将其作为完整数组返回。

let results = fetch(this.props.url)
        .then((res) => {
            return res.json();
        })
        .then((data) => {
            return data;
        })

1
尝试使用 await
而不是
var value = definitions.PromiseValue 

使用
var value =  await definiton;

这可能通过产生 promise 值来解决您的问题。 请注意,await 只能在 async 函数中使用,并且它是 ES2016 的一个特性。

请问您能否解释一下这个是如何达到目的的。谢谢! - Shanteshwar Inde

0

阅读手册,我们可以看到:

按设计,承诺的即时状态和值不能在代码中同步检查,而不调用then()方法。

为了帮助调试,仅当手动检查承诺对象时,您可以看到更多信息作为特殊属性,这些属性无法从代码中访问(目前,这是通过随机化属性名称来实现的,因为缺乏更复杂的语言或调试器支持)。

强调是我的。因此,你想做的事情是无法完成的。更好的问题是,为什么你需要像那样访问承诺状态?


-1

我认为这会与此相配得很好。

(async () => {
  let getDefinitions = await ( () => {
    return new Promise( (resolve, reject) => {
      resolve(ContactManager.request("definition:entities"));
    });
  })();
)();

-4

对于返回的响应是HTML而不是JSON的情况

fetch('http://localhost:3000/hello')
  .then(response => response.text())
  .then(data => {
    // you can see your PromiseValue data here
    console.log(data)
  })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接