Reputation: 364
I've tried mixing Promises
with ES6 destructuring syntax (just for experimentation purposes) but the following code throws an error:
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!`)
})
On Node.js v7.10.1 it prints:
TypeError: Cannot read property 'Symbol(promise_state_symbol)' of undefined
Chrome console also throws a TypeError
, but with a different message:
Uncaught TypeError: Method Promise.prototype.then called on incompatible receiver undefined
These errors don't say much to me. What's better explanation for this?
Upvotes: 0
Views: 6777
Reputation: 2935
You are Assigning the then
method to a variable, but then
accesses this
. You could use bind
to achieve what you want.
Basically methods in javascript are just functions that are using this
. If you are “stealing” the function and don't supply a this value, you are in dangerous territory.
Also the then
you're extracting is most likely from Promise.prototype
, not a function specific to the delay function.
You just found a fancy way to get the method from the object. It has not much to do with destucturing at all…
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')
But you want a then
, that somehow ensures, that you call it on the right promise.
So you could either go with
const p = delay(2000);
const then = p.then.bind(p);
…
Or construct another anonymous function
const p = delay(2000);
const then = fn => p.then(fn)
Note that this is not what you want, because it start the timeout when you are calling your then
.
const then = fn => delay(2000).then(fn) // ⚠ setTimeout gets called when you are calling then.
I see no way how you would achieve what you want in one line, but maybe others have an idea.
Upvotes: 1
Reputation: 665286
It means that then
is a method and you did not call it on any instance - you just called it as a function without any this
context (or "receiver", as the second error message names it properly). You essentially did
const then = Promise.prototype.then
console.log(typeof then) // ==> 'function'
then(() => {}) // throws TypeError
You could use call
const promise = delay(2000);
then.call(promise, console.log);
or just properly invoke promise.then(console.log)
.
Upvotes: 3