传回承诺并在其他地方解决它

时间:2018-02-02 20:14:14

标签: javascript promise

我想用Promises替换我代码中的一些回调。

我有一个使用setAnimationFrame在循环中运行的模型。我想在我的模型中启动一些东西并在完成后通知我。目前我是这样做的。

doSomething(callback) {
   this._doSomething = true
   this._doneCallback = callback
}   

step() {
  ...
  if (this._doSomething) {
    doItEveryStep();
    if (success) {
      this._doneCallback()
    }
  }
  requestAnimationFrame(step)
}

我想使用promises,所以我可以使用model.doSomething().then( () => ... )

而不是使用回调

以下是我认为这样做的好方法:

doSomething() {
   this._doSomething = true
   this._successPromise = new Promise()
   return this._successPromise
}   

step() {
  ...
  if (this._doSomething) {
    doItEveryStep();
    if (success) {
      this._successPromise.resolve()
    }
  }
  requestAnimationFrame(step)
}

但是,显然我不能只创建new Promise(),因为我需要将调用resolve的函数传递给Promise。但我很困惑,因为我不想触发一些异步代码 - 异步代码已经发生。我只是希望能够在现有的异步循环中触发一些事情,并告诉我它何时完成。

显然,我认为这一切都错了。我是否应该尝试将doSomething视为承诺?

2 个答案:

答案 0 :(得分:2)

您通常会拥有所有异步代码,这些代码可以实现在promise构造函数回调中编码的promise。

真的你需要不同的颜色,然后你可以这样做,但我认为这不是一个理想的模式:保存对resolve的引用你从promise构造函数得到的函数:

doSomething() {
    this._doSomething = true
    return new Promise( (resolve, reject) => {
        this.resolve = resolve; // Save the reference
    })
    // We don't need a reference to this._successPromise 
}   

step() {
  ...
  if (this._doSomething) {
    doItEveryStep();
    if (success) {
      this.resolve() // We have the reference
    }
  }
  requestAnimationFrame(step)
}

答案 1 :(得分:1)

如果你真的想在这里使用诺言,我可以看到两种选择。首先,保持回调并使用它来解决承诺:

doSomething() {
   this._doSomething = true

   // The || is to prevent the promise from being recreated if this
   // method is called twice.
   this._successPromise = this._successPromise || new Promise((resolve, reject) => {
       this._doneCallback = resolve
   })
   return this._successPromise
}   

step() {
  ...
  if (this._doSomething) {
    doItEveryStep();
    if (success) {
      this._doneCallback() // Resolves the original promise...
    }
  }
  requestAnimationFrame(step)
}

否则,您可以创建一个包装承诺的帮助程序类,并公开其解析和拒绝函数:

class Deferred {
    promise;
    resolve;
    reject;

    constructor() {
        this.promise = new Promise((resolve, reject) => {
            this.resolve = resolve;
            this.reject = reject;
        })
    } 
}

doSomething() {
   this._doSomething = true
   this._successPromise = this._successPromise || new Deferred()
   return this._successPromise.promise
}   

step() {
  ...
  if (this._doSomething) {
    doItEveryStep();
    if (success) {
      this._successPromise.resolve()
    }
  }
  requestAnimationFrame(step)
}