I’m doing a deep dive into ES6 native Promises. Along the way I came across some articles that quote Douglas Crockford design choices regarding not using things like new
, Object.create
, this
, etc. Some people are advocating the use of Factory Functions over constructors. I have also learnt that there is a lot of heated debate regarding those choices. So to avoid having this question listed as not constructive, I’d like to ask this specific question.
How can I create a factory function for a Promise without using new?
// from [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) var promise1 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, 'foo'); }); console.log(promise1); // expected output: [object Promise]
This is also true for using things like building a new Headers()
for a fetch
.
At some point in the factory function, I’m going to have to write:
new Promise();
Are DC and the other authors referring to custom objects only, and not builtins? What about all the other API’s that require the use of new?
Advertisement
Answer
If you have a “class-like” function that requires you to call it with new
keyword you could convert it to a factory function using Object.create
function. Like this
function Person(name) { this.name = name; } Person.prototype.sayHi = function() { console.log(this.name); } const makePerson = (name) => { const person = Object.create(Person.prototype); Person.call(person, name); return person; } makePerson('Joe').sayHi()
But this wont work with Promise because (from spec)
Promise is not intended to be called as a function and will throw an exception when called in that manner.
const makePromise = (executor) => { const promise = Object.create(Promise.prototype); Promise.call(promise, executor); //this line throws return promise; } try { makePromise(resolve => setTimeout(resolve, 1000, 'Hi!')).then(console.log) } catch(e) { console.error('Crashed due to ', e.message) }
Again but there is an ultimate factory that comes with Reflect API Reflect.construct
. So if you want to avoid using new
at all costs you could do it like this
const makePromise = (executor) => { return Reflect.construct(Promise, [executor], Promise) } makePromise(resolve => setTimeout(resolve, 1000, 'Hi!')) .then(console.log);