最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to convert triggerevent into Promise or asyncawait? - Stack Overflow

programmeradmin2浏览0评论

I am trying to convert a callback function to async/await. The code uses postMessage from the main window frame to an iframe. When the iframe posts a message back, it calls the callback function. Is there any way to convert to Promise from the $(window).on(...) pattern?

Minimal version of working code:

To call the function:

window.bridge.post(cb);

Bridge object:

class Bridge {
  constructor(win, root) {
    this.win = win;
    this.root = root;
    this.bindEvents();

    this.post = this.factoryMethod('post', 'postResult');

  }

  post(eventName, paramObject) {
    this.win.postMessage([eventName, JSON.stringify(paramObject)], this.root);
  }

  bindEvents() {
    window.addEventListener('message', e => this.handleEvents(e));
  }

  handleEvents(e) {
    const eventName = e.data[0];
    const eventObj = e.data[1];
    if (typeof eventName !== 'undefined' && eventName != null) {
      $(window).trigger(eventName, eventObj);
    }
  }

  factoryMethod(msgIn, msgOut) {
    return (cb) => {
      this.post(msgIn, {});
      $(window).on(msgOut, (e, arg) => cb(arg));
    };
  }

}

export default Bridge;

Thanks in advance.

I am trying to convert a callback function to async/await. The code uses postMessage from the main window frame to an iframe. When the iframe posts a message back, it calls the callback function. Is there any way to convert to Promise from the $(window).on(...) pattern?

Minimal version of working code:

To call the function:

window.bridge.post(cb);

Bridge object:

class Bridge {
  constructor(win, root) {
    this.win = win;
    this.root = root;
    this.bindEvents();

    this.post = this.factoryMethod('post', 'postResult');

  }

  post(eventName, paramObject) {
    this.win.postMessage([eventName, JSON.stringify(paramObject)], this.root);
  }

  bindEvents() {
    window.addEventListener('message', e => this.handleEvents(e));
  }

  handleEvents(e) {
    const eventName = e.data[0];
    const eventObj = e.data[1];
    if (typeof eventName !== 'undefined' && eventName != null) {
      $(window).trigger(eventName, eventObj);
    }
  }

  factoryMethod(msgIn, msgOut) {
    return (cb) => {
      this.post(msgIn, {});
      $(window).on(msgOut, (e, arg) => cb(arg));
    };
  }

}

export default Bridge;

Thanks in advance.

Share Improve this question asked May 12, 2017 at 5:32 Ricky HanRicky Han 1,3771 gold badge15 silver badges26 bronze badges 3
  • 2 new Promise(resolve => $(window).once(msgOut, resolve))? – Bergi Commented May 12, 2017 at 5:42
  • Is it once or on? Will this allow window.bridge.post().then(fun)? I think the post function has to return a Promise right? – Ricky Han Commented May 12, 2017 at 6:02
  • once - promises can only settle at a single time, for multiple messages you need separate promises. That's why they're not exactly well suited for a stream of events. And if you allow asynchronous concurrent messaging, it gets quite a lot more plicated than that anyway. – Bergi Commented May 12, 2017 at 6:12
Add a ment  | 

2 Answers 2

Reset to default 6

Thanks to Bergi's ment I am able to convert it to Promise.

factoryMethod(msgIn, msgOut) {                                                                                                                                                                                  
  return (ann)  => new Promise((resolve, reject) => {                        
    this.post(msgIn, ann);                                                                                                                                                                                      
    $(window).on(msgOut, (e, arg) => resolve(arg));                                                                                                           
  });                                                                                                                                                                                                           
}    

This returns a higher order function that returns a Promise.

Perhaps already answered, but this is how I do it typically:

// given you've defined this `Future` fn somewhere:
const Future = fn => {return new Promise((r,t) => fn(r,t))}

// define an eventFn that takes a promise `resolver`
const eventFn = resolve => {
  // do event related closure actions here. When finally done, call `resolve()`
  something.oneventfired = e => {resolve(e)}
}

// invoke eventFn in an `async` workflowFn using `Future`
// to obtain a `promise` wrapper
const workflowFn = async () => {await Future(eventFn)}

Especially for things like indexedDb event wrappers to simplify usage.

Or you might find this variation of Future to be more general purpose

class PromiseEx extends Promise {
  resolve(v,...a) {
    this.settled = true; this.settledValue = v;
    return(this.resolve_(v,...a))
  }
  reject(v,...a) {
    this.settled = false; this.settledValue = v;
    return(this.reject_(v,...a))
  }
  static Future(fn,...args) {
    let r,t,ft = new PromiseEx((r_,t_) => {r=r_;t=t_})
    ft.resolve_ = r; ft.reject_ = t; fn(ft,...args);
    return(ft)
  }
}
发布评论

评论列表(0)

  1. 暂无评论