请问如何将监听事件改为promise的形式

melongz
  • 25

现在的代码结构是这样:

function receiver(type, callback) {
  document.addEventListener(type, (ev) => {
    callback(ev);
  });
}

然后通过回调函数来执行:

receiver('click', (ev) => {
  console.log(ev)
})

现在想改为promise的形式:

receiver('click').then(ev => {
  console.log(ev)
})

请问需要怎么修改?

回复
阅读 2.6k
5 个回答

Promise就像一个状态机,而且是一个状态不可逆的状态机,这就意味它只会在到达Fullfiled或者Rejected状态时会执行你注册的函数,所以用Promise实现是不合适的
但是可以写成这样以达成相似效果

function receiver(type) {
  const listeners = [];

  const listen = {
    then(callback) {
      listeners.push(callback);

      return listen;
    }
  };
  document.addEventListener(type, async (ev) => {
    let acc = ev;
    for (let i = 0; i < listeners.length; ++i) {
      acc = await listeners[i](acc);
    }
  });

  return listen;
}

receiver("click")
  .then((e) => {
    console.log(e);

    return 1;
  })
  .then((v) => {
    console.log(v);
  });

简单的就是链式调用,回调函数放入fns中

function receiver(type) {
    let callbacks = {
        fns: [],
        then: function(cb){
            this.fns.push(cb) 
            return this
        }
    }
  document.addEventListener(type, function(ev) {
    let fns = callbacks.fns.slice()
    for(let i = 0, l = fns.length; i < l; i++){
        fns[i].call(this, ev)
    }
  });

  return callbacks
}

image.png

Promise 是处理单次的情况,需要多次的话不能用 Promise,Rxjs 当然是最合适的选择,但要说这个代码改造的话,形式上还是可以(不是 Promise,只是像)

function receiver(type) {
    const callbacks = [];

    document.addEventListener(type, (ev) => {
        callbacks.forEach(fn => fn(ev));
    });

    return {
        then(callback) {
            callbacks.push(callback);
        }
    };
}

这样用

receiver("click").then(() => console.log("hello"));
receiver("click").then(() => console.log("hi"));

const click = receiver("click");
click.then(() => console.log("aaaaa"));
click.then(() => console.log("bbbbbb"));

反正每调一次 receiver("click") 就会注册一次 click 事件,也可以改造一下变成一个:

const receiver = (() => {
    const callbacks = {};

    return function (type) {
        const list = callbacks[type];
        if (!list) {
            document.addEventListener(type, (ev) => {
                callbacks[type].forEach(fn => fn(ev));
            });
        }

        return {
            then(callback) {
                (callbacks[type] ??= []).push(callback);
            }
        };
    };
})();

其实用起来也没啥区别,

Promise只能fulfilled一次,用rxjs吧
https://www.learnrxjs.io/lear...

https://rxjs-dev.firebaseapp....

import { fromEvent } from 'rxjs';

const clicks = fromEvent(document, 'click');
clicks.subscribe(x => console.log(x));

// Results in:
// MouseEvent object logged to console every time a click
// occurs on the document.

普通函数返回 Promise

function receiver(type) {
  return new Promise(resolve=>{
    document.addEventListener(type, (ev) => {
       resolve(ev);
    });
  })
}
receiver('click').then(ev=>{
 ……
})
你知道吗?

宣传栏