Search code examples
javascriptnode.jsfunctionsyntaxarrow-functions

What's the correct syntax for a named arrow function registered as callback?


I'm having trouble understanding how could I replace a function declaration that is registered as a callback. This snippet works as intended:

const http = require('http');
const fs = require('fs');
const url = require('url');
const ct = { 'Content-Type': 'text/html' };

http.createServer((req, res) => {

  let q = url.parse(req.url, true);
  if (q.pathname === "/") {
    fs.readFile('./index.html', renderIndex);
  }

function renderIndex(err, data) {
    if (err) throw err;
    res.writeHead(200, ct);
    console.log("Rendering index");
    return res.end(data);
  }
}).listen(8080)

However, I was wondering if it were possible to refactor the renderIndex declaration into an arrow function.

I know from testing that a function expression wouldn't work. So this is not possible:

...
const renderIndex = function (err, data) {
    if (err) throw err;
    res.writeHead(200, ct);
    console.log("Rendering index");
    return res.end(data);
  }
...

And so neither is:

...
const renderIndex = (err, data) => {
    if (err) throw err;
    res.writeHead(200, ct);
    console.log("Rendering index");
    return res.end(data);
  }
...

But is there a valid arrow function syntax that would enable me to register renderIndex as a callback in fs.readFile('./index.html', renderIndex);... perhaps refactoring that line as well?

Thanks!


Solution

  • If you move the function definition before the line where it's used, it should work. Like this:

    http.createServer((req, res) => {
    
      const renderIndex = (err, data) => {
        if (err) throw err;
        res.writeHead(200, ct);
        console.log("Rendering index");
        return res.end(data);
      }
    
      let q = url.parse(req.url, true);
      if (q.pathname === "/") {
        fs.readFile('./index.html', renderIndex);
      }
    }).listen(8080)
    

    If it were my code, I would move the function definition outside of the containing function, completely, currying it so I can pass res to it before it's used as a callback:

    const renderIndex = res => (err, data) => {
      if (err) throw err;
      res.writeHead(200, ct);
      console.log("Rendering index");
      return res.end(data);
    }
    
    http.createServer((req, res) => {
      let q = url.parse(req.url, true);
      if (q.pathname === "/") {
        fs.readFile('./index.html', renderIndex(res));
      }
    }).listen(8080)