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
oron
? Will this allowwindow.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
2 Answers
Reset to default 6Thanks 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)
}
}