创建(ES6)承诺而不开始解决它

Bar*_*ast 60 javascript promise es6-promise

使用ES6承诺,如何在不定义解析逻辑的情况下创建承诺?这是一个基本的例子(一些TypeScript):

var promises = {};
function waitFor(key: string): Promise<any> {
  if (key in promises) {
    return promises[key];
  }
  var promise = new Promise(resolve => {
    // But I don't want to try resolving anything here :(
  });

  promises[key] = promise;
  return promise;
}

function resolveWith(key: string, value: any): void {
  promises[key].resolve(value); // Not valid :(
}
Run Code Online (Sandbox Code Playgroud)

使用其他promise库可以轻松完成.以JQuery为例:

var deferreds = {};
function waitFor(key: string): Promise<any> {
  if (key in promises) {
    return deferreds[key].promise();
  }
  var def = $.Deferred();    
  deferreds[key] = def;
  return def.promise();
}

function resolveWith(key: string, value: any): void {
  deferreds[key].resolve(value);
}
Run Code Online (Sandbox Code Playgroud)

我能看到做到这一点的唯一方法是将解析函数存储在promise的执行程序中,但这似乎很麻烦,而且我不确定它是在运行这个函数的时候定义的 - 它是否总是在构造时立即运行?

谢谢.

Ben*_*aum 71

好问题!

传递给promise构造函数的解析器故意运行同步以支持此用例:

var deferreds = [];
var p = new Promise(function(resolve, reject){
    deferreds.push({resolve: resolve, reject: reject});
});
Run Code Online (Sandbox Code Playgroud)

然后,在稍后的某个时间点:

 deferreds[0].resolve("Hello"); // resolve the promise with "Hello"
Run Code Online (Sandbox Code Playgroud)

promise构造函数的原因是:

  • 通常(但不总是)解析逻辑与创建绑定.
  • promise构造函数是throw安全的,并将异常转换为拒绝.

有时它不适合它,并且旋转变压器同步运行.以下是有关该主题的相关阅读.

  • @Barguast 当然,对于 ES6 特别是 - http://www.ecma-international.org/ecma-262/6.0/index.html#sec-newpromisecapability 是承诺的构造方式,它调用 http://www.ecma- International.org/ecma-262/6.0/index.html#sec-construct 被同步调用。它又从 http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise-executor 同步调用 - 我认为旧的 https://github.com/promises-aplus /constructor-spec 是更好的来源。 (2认同)
  • @BenjaminGruenbaum:只是指向[JavaScript承诺回调是否异步执行](http://stackoverflow.com/q/29963129/1048572):-) (2认同)

Man*_*anu 44

我想在这里加2美分.考虑到" 创建es6 Promise而不开始解决它 "的问题,我解决了它创建一个包装器函数并调用包装器函数.码:

假设我们有一个f返回Promise 的函数

/** @return Promise<any> */
function f(args) {
   return new Promise(....)
}

// calling f()
f('hello', 42).then((response) => { ... })
Run Code Online (Sandbox Code Playgroud)

现在,我想准备一个电话f('hello', 42)而不实际解决它:

const task = () => f('hello', 42) // not calling it actually

// later
task().then((response) => { ... })
Run Code Online (Sandbox Code Playgroud)

希望这会帮助别人:)


Promise.all()在评论中提到引用(并由@Joe Frambach回答),如果我想准备调用f1('super')&f2('rainbow'),2,返回promises的函数

const f1 = args => new Promise( ... )
const f2 = args => new Promise( ... )

const tasks = [
  () => f1('super'),
  () => f2('rainbow')
]

// later
Promise.all(tasks.map(t => t()))
  .then(resolvedValues => { ... })
Run Code Online (Sandbox Code Playgroud)


sea*_*ley 5

JavaScript 领域的情况正在慢慢好转,但在这种情况下,事情仍然不必要地复杂。这是一个公开解析和拒绝函数的简单助手:

Promise.unwrapped = () => {
  let resolve, reject, promise = new Promise((_resolve, _reject) => {
    resolve = _resolve, reject = _reject
  })
  promise.resolve = resolve, promise.reject = reject
  return promise
}

// a contrived example

let p = Promise.unwrapped()
p.then(v => alert(v))
p.resolve('test')
Run Code Online (Sandbox Code Playgroud)

显然曾经有一个Promise.defer帮助者,但即便如此,仍然坚持将延迟对象与承诺本身分开......