双括号在javascript中是什么意思,以及如何访问它们


76

情况

我有以下使用Promise的函数。

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

var definitions = getDefinitions()

的内容definitions是:

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

PromiseValue直接访问属性返回未定义

var value = definitions.PromiseValue; // undefined

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


2
这将有助于了解您正在使用哪个库。
JJJ 2015年

4
嗯,我想我正在使用内置的JavaScript库和Chrome(??)
Jeff

2
看起来就是承诺状态的描述方式。您可以在Chrome的控制台中尝试此操作:new Promise(function(){})。该[[PromiseStatus]]浏览器可以相比<state>的Firefox。我真的不明白这里的问题是什么(假设OP知道诺言是什么)。
DenysSéguret2015年

1
据我所知,@ Jeff就是Chrome向您显示承诺状态的方式。这些属性在对象外部故意不可见。如果您在Firefox中查看Promise对象,它不会以这种方式显示。我认为这可能只是为了提供诊断帮助。
尖尖的2015年

1
什么ContactManager.request("definition:entities")
本杰明·格伦鲍姆

Answers:


105

里面有什么东西 [[]]

我的问题是括号[[]]是什么意思,以及如何检索[[PromiseValue]]的值。

这是内部财产。您不能直接访问它。本地承诺只能then与承诺一起包装,或者通常只能以异步方式进行包装-请参阅如何从异步调用返回响应。引用规范:

它们仅出于说明目的由本规范定义。ECMAScript的实现必须表现为好像它以此处描述的方式对内部属性进行了生产和操作。内部属性的名称括在双方括号[[]]中。当算法使用对象的内部属性并且该对象未实现所指示的内部属性时,将引发TypeError异常。

你不能

认真地-他们是什么?

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

不要告诉任何人,但这些实际上是私人符号。它们存在的原因是其他内部方法能够访问[[PromiseValue]]。例如,当io.js决定返回promise而不接受回调时,这将使它在保证的情况下快速访问这些属性。他们没有暴露在外面。

我可以访问它们吗?

除非您自己制作Chrome或V8版本,否则不要这么做。也许在ES7中带有访问修饰符。截至目前,由于它们还不是规范的一部分,将无法通过浏览器中断-抱歉。

那么我如何获得我的价值?

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

但是,如果返回错误怎么办?为了应对这些情况,请在.then()的末尾(或外部)添加以下内容。

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

尽管我不得不猜测-您没有正确地开始转换API,因为这种转换仅在方法是同步的情况下才起作用(在这种情况下,不返回诺言),或者它已经返回了诺言,这将使它解决了(这意味着您根本不需要转换return


另外应该说,它完全违背了a的目的,即Promise在之外访问其包装值then。a的目的Promise是从一个非阻塞函数的缺失返回值中抽象出来,即aPromise代表“未来值”。一旦暴露了这个“未来值”(在之外then),这些抽象将在整个计算中立即丢失。

如果诺言被拒绝,那么这些值将通过.catch((values) => {})而不是在.then(() => {})
jony89 '17

@Benjamin,您是说内部插槽和内部方法是由JS引擎根据规范实现的吗?我读了一个回答,说,它们只是文字,没有实现。(在这里我可能会误会)而且,我并不是在承诺的背景下提问,因为我现在对此并不了解。只是一般地询问,例如[[PUT]] [[Prototype]]等
945945

通常,@ Number945[[PromiseValue]]在devtools中实际上是由devtools生成的-当您在控制台上按Enter时,它会执行以下操作evaluateOnCallFrame,并将消息发送到V8,V8返回子类型的RemoteObject promise。对此工作有明确的临时支持。上面的答案是正确的(那是检查员从中获取这些属性的地方),但不是准确的(那不是它们到达那里的方式-它们是通过显式的调试器支持到达那里的)
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()”立即执行,因此传递给“ .then()”的参数就是在仍未解决promise的情况下执行的任何常量(字符串,对象或数字)。也许您不理解“ .then()”期望函数作为其参数。
IAM_AL_X

@IAM_AL_X呵呵。我也无法理解我的评论。两年后,我唯一能想到的就是我要引用“ console.log”这一行,并且完全输入错误。确实.then(data => { console.log(data)})可以简化为事实,.then(console.log)但是您绝对正确,该函数需要访问该函数的常量。抱歉给您带来任何混乱
jymbob

5

这个例子是带有react的,但是在大多数情况下应该是一样的。

将此this.props.url替换为您的url,以使其适用于大多数其他框架。

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

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

0

阅读联机帮助页,我们可以看到:

通过设计,不能在不调用then()方法的情况下从代码同步检查promise的即时状态和值。

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

强调我的。因此,您想做的事情无法完成。更好的问题是为什么您需要这样访问promise状态?


0

尝试使用await

代替

var value = definitions.PromiseValue 

使用

var value =  await definiton;

这可以通过产生承诺值来解决您的目的。

请注意, await只能在异步函数中使用,它是ES2016的功能。


你能解释一下这个解决目的。谢谢!
Shanteshwar Inde

-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)
  })
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.