我尝试将Promises
与ES6解构语法混合(仅用于实验目的),但以下代码会引发错误:
function delay(ms) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), ms)
})
}
const { then } = delay(2000)
console.log(typeof then) // ==> 'function'
// throws TypeError:
then(() => {
console.log(`done!`)
})
在Node.js v7.10.1上打印:
TypeError:无法读取未定义的属性'Symbol(promise_state_symbol)'
Chrome控制台还会抛出TypeError
,但会显示不同的消息:
Uncaught TypeError:方法Promise.prototype.then调用不兼容的接收器undefined
这些错误对我说不多。对此有什么更好的解释?
答案 0 :(得分:3)
这意味着then
是一种方法而你没有在任何实例上调用它 - 你只是把它称为一个没有this
context的函数(或者#34;接收器",as as第二条错误消息正确命名它)。你基本上做了
const then = Promise.prototype.then
console.log(typeof then) // ==> 'function'
then(() => {}) // throws TypeError
您可以使用call
const promise = delay(2000);
then.call(promise, console.log);
或只是正确调用promise.then(console.log)
。
答案 1 :(得分:1)
您正在为变量分配then
方法,但then
访问this
。您可以使用bind
来实现您想要的目标。
基本上,javascript中的方法只是使用this
的函数。如果您“窃取”该功能并且没有提供此值,则您处于危险区域。
您提取的then
最有可能来自Promise.prototype
,而不是特定于延迟功能的功能。
你刚刚发现了一种从对象中获取方法的奇特方法。它完全没有与去除相关...
let p;
const {then} = p = delay(2000);
const then1 = p.then;
console.assert(then === Promise.prototype.then)
console.assert(then1 === then, 'thens aren\'t the same')
但你想要一个then
,以某种方式确保你在正确的承诺上称之为。{/ p>
所以你可以选择
const p = delay(2000);
const then = p.then.bind(p);
…
或构建另一个匿名函数
const p = delay(2000);
const then = fn => p.then(fn)
请注意,这不是您想要的,因为它会在您拨打then
时启动超时。
const then = fn => delay(2000).then(fn) // ⚠ setTimeout gets called when you are calling then.
我认为你不可能在一条线上实现你想要的东西,但也许其他人有一个想法。