简体   繁体   中英

ES6 native Promise from Factory Function

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM