来自Factory Function的ES6原生承诺

时间:2018-01-30 07:05:36

标签: javascript javascript-events promise

我正在深入研究ES6原生Promise。在此过程中,我发现了一些引用Douglas Crockford design choices关于使用newObject.createthis等内容的 not 的文章。有些人是主张使用Factory Functions而不是构造函数。我还了解到有很多关于这些选择的heated debate。因此,为了避免将此问题列为而非建设性,我想问一下这个具体问题。

如何在不使用 new 的情况下为Promise创建工厂函数

// 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]

对于使用为Headers()构建 fetch之类的内容也是如此。

在工厂功能的某个时刻,我将不得不写:

new Promise();

DC和其他作者是否只引用自定义对象,而不是内置对象?那些需要使用 new 的所有其他API's呢?

2 个答案:

答案 0 :(得分:0)

无论如何,您需要在某个地方拨打new关键字。你已经完成了99%。

function promiseFactory(bodyFunc) {
  return new Promise(bodyFunc);
}

并使用

const promise = promiseFactory((resolve, reject) => setTimeout(resolve, 100, 'foo'));

实施例

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

如果您想使用已经解决或拒绝的Promise,则可以分别使用Promise.resolvePromise.reject

答案 1 :(得分:0)

如果你有一个“类似”的功能需要你用new关键字来调用它,你可以使用Object.create函数将它转换为工厂函数。喜欢这个

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()

但这不适用于Promise,因为(来自规范)

  

Promise并不打算作为一个函数调用,而是抛出一个函数   以这种方式调用时的异常。

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)
}

再次有一个终极工厂,它附带Reflect API Reflect.construct。因此,如果您想不惜一切代价避免使用new,可以像这样做

const makePromise = (executor) => {
  return Reflect.construct(Promise, [executor], Promise)
}

makePromise(resolve => setTimeout(resolve, 1000, 'Hi!'))
  .then(console.log);