Ясный способ прослушивания одного события

Я просто опишу ответ Берги (в частности, вторую часть) немного, потому что мне очень понравилось, как это было сделано, но я хочу, чтобы опция останавливала таймер после его запуска ( как clearInterval() почти). Sooo ... Я завернул его в конструктор, чтобы мы могли делать с ним «объективные» вещи.

1. Конструктор

Хорошо, поэтому вы копируете / вставляете это ...

/**
 * Self-adjusting interval to account for drifting
 * 
 * @param {function} workFunc  Callback containing the work to be done
 *                             for each interval
 * @param {int}      interval  Interval speed (in milliseconds) - This 
 * @param {function} errorFunc (Optional) Callback to run if the drift
 *                             exceeds interval
 */
function AdjustingInterval(workFunc, interval, errorFunc) {
    var that = this;
    var expected, timeout;
    this.interval = interval;

    this.start = function() {
        expected = Date.now() + this.interval;
        timeout = setTimeout(step, this.interval);
    }

    this.stop = function() {
        clearTimeout(timeout);
    }

    function step() {
        var drift = Date.now() - expected;
        if (drift > that.interval) {
            // You could have some default stuff here too...
            if (errorFunc) errorFunc();
        }
        workFunc();
        expected += that.interval;
        timeout = setTimeout(step, Math.max(0, that.interval-drift));
    }
}

2. Мгновенное действие

Скажите, что делать и все это ...

// For testing purposes, we'll just increment
// this and send it out to the console.
var justSomeNumber = 0;

// Define the work to be done
var doWork = function() {
    console.log(++justSomeNumber);
};

// Define what to do if something goes wrong
var doError = function() {
    console.warn('The drift exceeded the interval.');
};

// (The third argument is optional)
var ticker = new AdjustingInterval(doWork, 1000, doError);

3. Тогда сделайте ... stuff

// You can start or stop your timer at will
ticker.start();
ticker.stop();

// You can also change the interval while it's in progress
ticker.interval = 99;

Я имею в виду, это работает для меня в любом случае. Если есть лучший способ, знаете ли.

-1
задан JGuo 13 July 2018 в 19:49
поделиться

3 ответа

Вы можете создать свой собственный абстрактный класс, который реализует ChildEventListener, но не обеспечивает реализацию onChildAdded:

abstract class ChildAddedEventListener : ChildEventListener {
    override fun onCancelled(p0: DatabaseError) {
    }

    override fun onChildMoved(p0: DataSnapshot, p1: String?) {
    }

    override fun onChildChanged(p0: DataSnapshot, p1: String?) {
    }

    override fun onChildRemoved(p0: DataSnapshot) {
    }
}

Затем вы подклассифицируете ChildAddedEventListener и предоставляете только нужную реализацию:

class MyChildAddedEventListener: ChildAddedEventListener {
    override fun onChildAdded(p0: DataSnapshot, p1: String?) {
        // your code here
    }
}

При этом вы можете использовать его как выражение встроенного объекта при добавлении его в запрос:

query.addChildEventListener(object : ChildAddedEventListener() {
    override fun onChildAdded(p0: DataSnapshot, p1: String?) {
        subscriber.onNext(Value.parse(unitName, varName, p0))
    }
})
1
ответ дан Doug Stevenson 17 August 2018 в 12:10
поделиться

Вы можете сделать

object EmptyChildEventListener : ChildEventListener {
     override fun onCancelled(p0: DatabaseError) {}
     override fun onChildChanged(p0: DataSnapshot, p1: String?) {}
     override fun onChildMoved(p0: DataSnapshot, p1: String?) {}
     override fun onChildRemoved(p0: DataSnapshot) {}
     override fun onChildAdded(p0: DataSnapshot, p1: String?) { }
} 

ref.addChildEventListener(object : ChildEventListener by EmptyChildEventListener {
     override fun onChildAdded(p0: DataSnapshot, p1: String?) {
         subscriber.onNext(Value.parse(unitName, varName, p0))
     }
})

EDIT: но вы можете, возможно, улучшить это так, например

inline fun DatabaseReference.onChildAdded(crossinline added: (DataSnapshot, String?) -> Unit) {
    this.addChildEventListener(object : ChildEventListener by EmptyChildEventListener {
         override fun onChildAdded(p0: DataSnapshot, p1: String?) = added(p0, p1)
    })
})

Теперь вы можете сделать

ref.onChildAdded { p0, p1 -> 
    subscriber.onNext(Value.parse(unitName, varName, p0))
}
0
ответ дан EpicPandaForce 17 August 2018 в 12:10
поделиться
  • 1
    Это лучшее, что я могу собрать на своем телефоне, я мог бы написать вам что-то с некоторой перекрестной линией – EpicPandaForce 13 July 2018 в 19:59
  • 2
    Проверьте мой пересмотренный ответ с моего ПК – EpicPandaForce 13 July 2018 в 20:50

Обычно имя шаблона, которое ommits всех методов называется Adapter, в вашем случае:

ref.addChildEventListener(object : ChildEventAdapter {
   override fun onChildAdded(p0: DataSnapshot, p1: String?) {
        subscriber.onNext(Value.parse(unitName, varName, p0))
    }
})

Класс адаптера (интерфейса) - это класс, который реализует интерфейс с пустыми методами, поэтому вы может выбрать, какой из них вы хотите переопределить

0
ответ дан Marcos Vasconcelos 17 August 2018 в 12:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: