You may merge the async "message" event listener and others like "error", "open", "close" etc, under one async iterable and consume with for await of
loop as follows. Note that we don't need to use an async generator here since we are yield
ing promises.
function wsMessageStream(url){
let _v, // previous resolve
_x, // previous reject
p = new Promise((v,x) => (_v = v, _x = x)),
ws = new WebSocket(url);
function* emitterGen(ws){
ws.addEventListener( "open"
, _ => ( _v({data: `Esatablished WebSocket connection for ${url}.`})
, p = new Promise((v,x) => (_v = v, _x = x))
)
);
ws.addEventListener( "close"
, _ => ( _v({data: `Closed WebSocket connection for ${url}.`})
, _v = null
, _x = null
)
);
ws.addEventListener( "message"
, m => ( _v(m)
, p = new Promise((v,x) => (_v = v, _x = x))
)
);
ws.addEventListener( "error"
, e => ( _x(e)
, p = new Promise((v,x) => (_v = v, _x = x))
)
);
while (_v || _x){
try{
yield p;
}
catch(e){
console.log(e);
}
}
return null;Promise.resolve(null); // finalize the iterable
}
return { stream: emitterGen(ws)
, socket: ws
};
}
let {stream,socket} = wsMessageStream('wss://ws.postman-echo.com/raw'),
counter = 0;
setTimeout(_ => socket.close(), 5000);
(async function(){
for await (let msg of stream){
console.log(`Message received: ${msg.data}`);
// run msg handlers here
socket.readyState === 1 && socket.send(`Thank you. ${counter++}`);
}
})();