Подтвердить что ты не робот

Создание настраиваемого события JavaScript

Я хотел бы создать пользовательское событие в JavaScript.

У меня есть приложение WPF с WebBrowser внутри и HTML-страница с JavaScript.

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

Затем я вызываю метод JavaScript OnPrinterStateChanged(state) с помощью функции InvokeScript элемента управления WebBrowser.

Проблема в том, что я должен реализовать метод OnPrinterStateChanged(state) на моей веб-странице. Я не могу изменить имя метода или подписаться/отказаться от подписки на событие...

Я хотел бы переместить JavaScript-метод OnPrinterStateChanged(state) в отдельный файл JavaScript.

Что я хочу:

  • Подписаться/Отменить подписку на мероприятие на моей странице HTML и решить, что я хочу делать, когда событие запускается (например: "function ChangeState" )
  • Когда событие .NET запускается, оно вызывает OnPrinterStateChanged(state) моего отдельного .js файла, затем запускается событие JavaScript и вызывается функция ChangeState.

Я нашел некоторые решения, но мне не удалось заставить их работать... Каков самый простой способ сделать это?

4b9b3361

Ответ 1

Возможно, что-то вроде этого?

function OnPrinterStateChanged(state) {
    var evt = new CustomEvent('printerstatechanged', { detail: state });

    window.dispatchEvent(evt);
}


//Listen to your custom event
window.addEventListener('printerstatechanged', function (e) {
    console.log('printer state changed', e.detail);
});

Альтернативным решением было бы использовать композицию функций, но тогда было бы трудно удалить конкретных слушателей.

function OnPrinterStateChanged(state) {}

function compose(fn1, fn2) {
    return function () {
        fn1.apply(this, arguments);
        fn2.apply(this, arguments);
    };
}

//Add a new listener
OnPrinterStateChanged = compose(OnPrinterStateChanged, function (state) {
    console.log('listener 1');
});

//Add another one
OnPrinterStateChanged = compose(OnPrinterStateChanged, function (state) {
     console.log('listener 2');
});

EDIT:

Здесь вы можете сделать это с помощью jQuery.

function OnPrinterStateChanged(state) {
    var evt = $.Event('printerstatechanged');
    evt.state = state;

    $(window).trigger(evt);
}


//Listen to your custom event
$(window).on('printerstatechanged', function (e) {
    console.log('printer state changed', e.state);
});

Ответ 2

Мне нравится использовать этот метод конструктора EventDispatcher, который, используя фиктивный элемент, изолирует события, чтобы они не были запущены ни по какому-либо существующему элементу DOM, ни по window или document.

Я использую CustomEvent а не createEvent потому что это новый подход. Узнайте больше здесь.

Мне нравится оборачивать каждый нативный метод следующими именами:

on, off, trigger

function EventDispatcher(){
    // Create a dummy DOM element 
    var dummy = document.createTextNode('');

    // Create custom wrappers with nicer names
    this.off = dummy.removeEventListener.bind(dummy);
    this.on = dummy.addEventListener.bind(dummy);
    this.trigger = function(eventName, data){
        if( !eventName ) return;
        var e = new CustomEvent(eventName, {"detail":data});
        dummy.dispatchEvent(e);
    }
}

////////////////////////////////////
// initialize the event dispatcher by creating an instance in an isolated way
var myEventDispatcher = new EventDispatcher();

////////////////////////////////////
// listen to a "foo" event
myEventDispatcher.on('foo', e =>{
    console.log(e.type, e.detail);
});

////////////////////////////////////
// trigger a "foo" event with some data
myEventDispatcher.trigger('foo', 123);

Ответ 3

Хорошо, я нашел решение.

Мне пришлось изменить версию IE WebBrowser на Internet Explorer 11: http://weblog.west-wind.com/posts/2011/May/21/Web-Browser-Control-Specifying-the-IE-Version

И затем:

function OnPrinterStateChanged(state) {

    var evt = document.createEvent("Event");
    evt.state = state;
    evt.initEvent("printerstatechanged", true, false);
    window.dispatchEvent(evt);

}


window.addEventListener('printerstatechanged', function (e) {
  // Do something
});

Ответ 4

Требование: ES6

let MyClass = (function () {
    let __sym = Symbol('MyClass');

    class MyClass {
        constructor() {
            this[__sym] = {};
        }
        on(event, callback) {
            this[__sym][event] = { callback: callback }
        }
        getError() {
            let event = this[__sym].error;

            if (event && event.callback) {
                event.callback('some parameter');
            }
        }
    }

    return MyClass;
}());

let myClass = new MyClass();

myClass.on('error', function (e) {
    console.log('error:', e);
});

console.log('before getting error:');

myClass.getError();