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 ?
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);
Anyway in some place you need to call the new
keyword. You have already done the 99%.
function promiseFactory(bodyFunc) {
return new Promise(bodyFunc);
}
And use this like
const promise = promiseFactory((resolve, reject) => setTimeout(resolve, 100, 'foo'));
Example
function promiseFactory(bodyFunc) { return new Promise(bodyFunc); } const promise1 = promiseFactory((resolve, reject) => setTimeout(resolve, 100, 'foo')); const promise2 = promiseFactory((resolve, reject) => setTimeout(resolve, 500, 'boo')); promise1.then(r => console.log(r)); promise2.then(r => console.log(r));
If you want to use already resolved or rejected Promise, you can use Promise.resolve and Promise.reject respectively.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.