然后在类中使用Javascript许诺

时间:2018-12-11 15:41:20

标签: javascript promise

我试图了解Promises的工作方式,而我的代码无法正常工作。

class Lights {
    constructor(delay) {
        this.blue = 0;
        this.green = 0;
        this.red = 0;
        this.delay = delay;
    }

    fadeIn(color, i) {
        var self = this;
        return new Promise(function(resolve, reject) {
            setTimeout(function () {
                self[color] = i;
                console.log(self[color]);
                i+=5;
                if (i <= 255) {
                    self.fadeIn(color, i);
                }
                resolve(self);
            }, self.delay);
        });
    }

    fadeOut(color, i) {
        var self = this;
        return new Promise(function(resolve, reject) {
            setTimeout(function () {
                self[color] = i;
                console.log(self[color]);
                i-=5;
                if (i >= 0) {
                    self.fadeIn(color, i);
                }
                resolve(self);
            }, self.delay);
        });
    }
}


var lights = new Lights(50);

lights.fadeIn("blue", 0).then(
    lights.fadeOut("blue", 255)
);

这里是代码的jsFiddle

代码背后的想法是将蓝色设置为0到255,将Then设置为255到0。我该怎么做?

2 个答案:

答案 0 :(得分:2)

您正在进行递归调用,因此在上一次调用时,您解析的不是您第一次调用then时的解析,因此您可以将第一个解析存储在类的一个属性中,然后调用它

class Lights {
  constructor(delay) {
    this.blue = 0;
    this.green = 0;
    this.red = 0;
    this.delay = delay;
    this.fadeInResolve = null;
    this.fadeOutResolve = null;
  }

  fadeIn(color, i) {
    return new Promise((resolve, reject) => {
      if (!this.fadeInResolve) {
        this.fadeInResolve = resolve
      }

      setTimeout(() => {
        this[color] = i;
        console.log(this[color]);
        i += 5;
        if (i <= 255) this.fadeIn(color, i);
        else this.fadeInResolve(this)
      }, this.delay);
    });
  }

  fadeOut(color, i) {
    return new Promise((resolve, reject) => {
      if (!this.fadeOutResolve) {
        this.fadeOutResolve = resolve
      }

      setTimeout(() => {
        this[color] = i;
        console.log(this[color]);
        i -= 5;
        if (i >= 0) this.fadeOut(color, i);
        else this.fadeOutResolve(this)
      }, this.delay);
    });
  }
}


var lights = new Lights(50);

lights.fadeIn("blue", 0).then(() => {
  console.log('Fade in done')
  lights.fadeOut("blue", 255).then(() => {
    console.log('Fade out done')
  })
});

答案 1 :(得分:1)

Promise.prototype.then()应该使用回调函数,并且递归不等待。考虑一下可用于执行相同操作的代码:

//promisify :)
function timer(delay) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve();
        }, delay);
    });
}

class _Modulator {
    constructor(_resolution = 255, _delay = 5) {
        /* assert resolution and delay > 0; */

        this._resolution = _resolution;
        this._delay = _delay;

        this._counter = 0;
        this._running = false;
    }

    start() {
        console.log("timer start");
        this._running = true;
        this._start();
    }

    _start() {
        return timer(this._delay).then(() => {
            if (this._running === true) {
                this._counter += 1;

                console.log("tick");
                this._onTick();

                /* care should be taken to ensure this will always catch, e.g., 
                 * correcting init
                 */
                if (this._counter === this._resolution) {
                    this._counter = 0;
                    this._onCycle();
                }

                this._start();
            }
        });
    }

    stop() {
        this._running = false;
        console.log("timer stopped");
    }

    _onTick() {
        console.log("tick handle: %s", this._counter);
    }

    _onCycle() {
        console.log("new cycle");
    }
}

class UpDownModulator extends _Modulator {
    constructor(_resolution = 255, _delay = 5) {
        super(_resolution, _delay);
        this._dir = 1;
    }

    _onTick() {
        console.log("tick handle: %s", this.getCounter());
    }

    _onCycle() {
        this._toggleDirection();
        console.log("new cycle: going %s", this.getDirection());
    }

    _toggleDirection() {
        this._dir ^= 1; 
    }

    getCounter() {
        return this._dir
            ? this._counter
            : this._resolution - this._counter;
    }

    getDirection() {
        return this._dir ? "up" : "down";
    }
}

let c = new UpDownModulator();

c.start();

您可以创建一个依赖于Modulator的ColorFader类并对其进行观察。这样会创建符合SRP的干净抽象。

我希望这会有所帮助!