Обещание Javascript тогда внутри класса

Я пытаюсь понять, как работают промисы, но не могу заставить работать свой фрагмент кода.

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.info(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.info(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. Как я могу это сделать?

lights.fadeIn("blue", 0).then(() => lights.fadeOut("blue", 255)); В противном случае ваше затухание будет выполнено до того, как ваше обещание будет выполнено.
Keith 11.12.2018 16:47

Чтобы прояснить, ваш then ожидает, что функция будет вызываться, когда она будет завершена, но то, что вы делаете, - это выполнение fadeOut и возвращение обещания от этого, поэтому оно выполняется до того, как это должно было произойти.

Senica Gonzalez 11.12.2018 16:52

Добавление к предыдущим комментариям; ваши методы fadeIn и fadeOut не дожидаются завершения затухания, чтобы выполнить обещание, поэтому fadeOut начнет работать до завершения fadeIn. Попробуйте заменить self.fadeIn(color, i); на return resolve(self.fadeIn(color, i));, то же самое касается метода fadeOut.

Jaime 11.12.2018 17:15

Также обратите внимание, что вы вызываете fadeIn из своего метода fadeOut, вероятно, не то, что вам нужно. Обновленная рабочий пример: jsfiddle.net/87haj6x9

Jaime 11.12.2018 17:23
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
4
79
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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.info(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.info(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.info('Fade in done')
  lights.fadeOut("blue", 255).then(() => {
    console.info('Fade out done')
  })
});

Я использовал ваш код для создания этот jsFiddle. Я попытался сделать одно затухание, затем одно затухание, затем снова затухание с другим цветом и, наконец, затухание. Но затухание никогда не запускается, подскажите почему?

Dipiks 12.12.2018 11:50

Поскольку вы должны установить для него значение null после его разрешения, вы также можете использовать async / await вместо всех тех, которые затем jsfiddle.net/hjx1az4n/1

Nenad Vracar 12.12.2018 11:57

Возможно ли внутри await запустить два fadeIn (которые могут разрешиться в разное время, дождаться разрешения обоих и затем выполнить другое действие?

Dipiks 12.12.2018 12:24

Конечно jsfiddle.net/hjx1az4n/3, но вам нужно настроить разные свойства для каждого цвета

Nenad Vracar 12.12.2018 12:40

Большое спасибо, это было очень полезно

Dipiks 12.12.2018 12:45

Рад, что смог помочь.

Nenad Vracar 12.12.2018 12:45

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.info("timer start");
        this._running = true;
        this._start();
    }

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

                console.info("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.info("timer stopped");
    }

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

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

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

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

    _onCycle() {
        this._toggleDirection();
        console.info("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();

Вы можете создать класс ColorFader, который зависит от модулятора, и наблюдать за ним. Это создает чистые абстракции, соответствующие SRP.

Надеюсь, это поможет!

Другие вопросы по теме