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?
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);