0

I am writing a Koa middleware that, on each request to the server, analyzes some input from a file on the server, and sends it over the websocket (using https://www.npmjs.com/package/ws) to the client.

This all works as expected, except for one problem. The data (as a result of analyzing the input from the file) updates properly, but doesn't update inside the websocket callback scope.

const websocket = new WebSocket.Server({ port: 8082 });

const sourceAST = parseJS();
const conditionResults = getConditionResults(sourceAST);

console.log('handling request', conditionResults); // <-- updates as expected every time

websocket.on('connection', ws => {
  console.log(conditionResults); // <-- not updated :(
  ws.send(
    JSON.stringify({
      type: 'feedback-updated',
      feedback: conditionResults,
    }),
  );
});

I can't seem to figure out why the conditionResults inside the ws callbacks is frozen on the first time it is ran, why it doesn't update each time this code is ran (on every request).

Edit: for context, the code snippet above lives inside a middleware function like this:

myMiddleware = async (ctx, next) => {
  await next();
  // my code snippet above
}

And the middleware is ran in Koa like so:

app.use(myMiddleware);

1 Answers1

0

If your middleware function can be initiated by another process, as well as a websocket message, something like this should work:

const websocket = new WebSocket.Server({port: 8082});

let sourceAST;
let conditionResults;

// Triggered by websocket message
websocket.on('message', data => {
    doThings()
});

// Triggered by your middleware
myMiddleware = async (ctx, next) => {
    await next();

    doThings()
};

function doThings () {
    sourceAST = getConditionResults(sourceAST);
    conditionResults = getConditionResults(sourceAST);
    console.log(conditionResults);

    websocket.send(
        JSON.stringify({
            type: 'feedback-updated',
            feedback: conditionResults,
        }),
    );
}
elight
  • 562
  • 2
  • 17
  • That did not fix it. I don't think my code is reassigning/redeclaring right? The JS code runs, finishes running entirely. Then a new request is made to the server, and the JS code is ran again, separate from the first run. Which is also why it's so surprising to me that the callback still references the old value. – Joren Broekema Mar 02 '20 at 20:45
  • Totally changed answer - not sure if that's the correct way to do it since now your comment doesn't apply. Sorry for any confusion.. – elight Mar 02 '20 at 21:01
  • Moving the parse() and getConditionResults() stuff inside the connection callback is a workaround to my problem, that I guess I will go with for now so thanks already for that insight! However, it doesn't solve the problem where I want data from outside the callback, where it is also updated, to sync inside the callback where I reference to it. – Joren Broekema Mar 02 '20 at 21:07
  • Seems like you should keep the `websocket` instance outside the scope of the middleware so you don't create a new instance each time..that's I think why previously the `connection` event alone worked for you. But instead you could let the connection stay alive and be managed by the one `websocket` instance and execute the cb on a `message` event. This way that cb block won't be reset each time. – elight Mar 02 '20 at 21:36
  • I'm not sure if it's possible to create the websocket in a way where it stays open during multiple requests, since Koa middlewares specifically target request-response, and are therefore ran on every request. So then the websocket will have to be created not as a or inside a middleware, but outside. And then my middleware needs to be able to access the websocket to send feedback updates whenever a request is made by the user. Will look into that I suppose, since it's probably better approach. – Joren Broekema Mar 02 '20 at 22:25