javascript - 使用 es6 模块创建自定义 "event listener"

标签 javascript

我们正在致力于在 Javascript 上创建自定义事件监听器。尝试了一些示例,但无法调用自定义事件监听器。代码示例:

events.js

function init() {
    return new Promise(() => {
        console.log('successfully initialized!');
    });
}

// this symbolizes some event occurring randomly. in reality, this will eventually be
// something like a webhook getting hit, or a websocket, etc. for now we just use
// setTimeout to simulate this event coming in at some time after init has been called
setTimeout(on, 15000);

// on is called anytime any event occurs. in this example, we hardcode that event1 occurred
function on() {
    console.log('event1 occurred in events.js');
    return 'event1';
}​

const events = {
    init,
    on,
};

export default events;

index.js

events.init(() => {
        // here we should see console log about successful initialization
    }).then(() => {
        // here, we want to "listen" for event1 to occur
        events.on('event1', () => {
            console.log('we were notified about event1 happening!');
        });
    });

在此示例中,我们看到浏览器控制台中显示以下内容

successfully initialized!

几秒钟后:

event1 occurred in events.js

如示例所示,index.js 中的“event1”回调代码永远不会被调用,而是调用 events.js 中的“on”函数。 我们需要的是一个自定义事件监听器来工作,这样我们就可以从index.js调用“event1”。console.log应该显示

we were notified about event1 happening!

感谢您查看问题并帮助解决问题。

最佳答案

我想说这里几乎没有问题。

<强>1。未兑现的 promise

首先,您没有解决 promise ,这意味着 then 回调永远不会被调用。

因此,首先您应该按如下方式更新 init 方法:

function init() {
  return new Promise((resolve) => {
    console.log('successfully initialized!');

    // when you're done with your stuff, tell outside
    resolve()
  });
}

<强>2。跟踪回调

然后,您没有跟踪不同类型事件的不同回调。 on 方法应该将元组事件回调保存在适当的映射中,如下所示:

const handlers = {}
function on(event, callback) {
  handlers[event] = callback;
}

<强>3。事件发射

我认为您缺少的最后一件事是事件“发射”的概念。当特定的事情发生时,您应该发出适当的事件。然后,如果它已注册回调,您将调用它。

因此,您需要向您的 events API 添加第三个 emit 方法,如下所示:

function emit(event) {
  const callback = handlers[event];

  // if we registered a callback before, and it is a function,
  // let's call it  
  if ( callback && typeof callback === 'function' )
    callback()
}

您的最终导出结果为:

const events = {
  init,
  on,
  emit
};

使用这一新方法,您可以模拟发出事件 event1 的调用,就像您正在注册的事件一样:

setTimeout(() => emit('event1'), 5000);

它似乎很有魅力:)

编辑

我不确定这是否是 @Shehzad Nizamani 要求的确切用例,但如果没有给出特定事件,我们可以 emit 触发所有已注册的回调,例如:

setTimeout(emit, 5000)

function emit(event) {
  if ( event ) {
    const callback = handlers[event];

    // if we registered a callback before, and it is a function,
    // let's call it  
    if ( callback && typeof callback === 'function' )
      callback()

  // if no event is given, we trigger all the callbacks
  } else {

    const callbacks = Object.values(handlers)
    callbacks.forEach(callback => {
      if ( typeof callback === 'function' )
        callback()
    })
  }
}

function init() {
  return new Promise((resolve) => {
    console.log('successfully initialized!');

    // when you're done with your stuff, tell outside
    resolve()
  });
}

// emit a specific event to trigger the relative callback
setTimeout(() => emit('event1'), 10000);
setTimeout(emit, 5000);

// we need to keep track of a map
// between event types and their callback
const handlers = {}
function on(event, callback) {
  handlers[event] = callback;
}

// we need a new api that triggers registered callbacks
function emit(event) {
  if ( event ) {
    const callback = handlers[event];

    // if we registered a callback before, and it is a function,
    // let's call it  
    if ( callback && typeof callback === 'function' )
      callback()

  // if no event is given, we trigger all the callbacks
  } else {

    const callbacks = Object.values(handlers)
    callbacks.forEach(callback => {
      if ( typeof callback === 'function' )
        callback()
    })
  }
}

const events = {
  init,
  on,
  emit
};

events.init(
  () => {
    // here we should see console log
    //about successful initialization
  }
).then(
  () => {
    
    // here, we want to "listen" for event1 to occur
    events.on('event1', () => {
      console.log('we were notified about event1 happening!');
    });
  }
);

关于javascript - 使用 es6 模块创建自定义 "event listener",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62093672/

相关文章:

javascript - 如何让 metisMenu 在鼠标悬停时自动展开?

javascript - 如何以编程方式将 Ace(vim 键盘布局)置于插入模式

javascript - 如何在一定数量后结束我的图像网格并添加额外的页面以滚动浏览?

javascript - AngularJS - 选择的 ng-model 无法正常工作

javascript - discord.js - 立即删除新添加的 react

javascript - BreezeJS "group by"方法

javascript - 如何在多个 JSON 对象中保存循环数据

javascript - 三.javascript中的JS + OOP,无法将3D JSON对象传递给其他类

javascript - 如何在按钮中隐藏 API 连接

javascript - 错误处理 promise 在 mongoDB 中保存唯一数据(ValidationError)