Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Build a Simple Dynamic Site with Node.js HTTP Methods and Headers Redirection Headers in Node.js

Tennyson Horn
Tennyson Horn
14,660 Points

Server crashes after displaying profile. Profile displays without avatar.

When I search "chalkers" I get successfully redirected to his profile, sans avatar image. But, it crashes the server.

The console logs the following error:

Server running at 127.0.0.1:8080
_http_outgoing.js:636
    nextTick(msg.socket[async_id_symbol],
                       ^

TypeError: Cannot read property 'Symbol(asyncId)' of null
    at write_ (_http_outgoing.js:636:24)
    at ServerResponse.write (_http_outgoing.js:630:10)
    at Object.view (/myLocalFilePath/renderer.js:18:12)
    at Profile.studentProfile.on (/myLocalFilePath/router.js:62:16)
    at emitOne (events.js:115:13)
    at Profile.emit (events.js:210:7)
    at ClientRequest.<anonymous> (/myLocalFilePath/profile.js:24:28)
    at Object.onceWrapper (events.js:316:30)
    at emitOne (events.js:115:13)
    at ClientRequest.emit (events.js:210:7)

here's my renderer.js:

const fs = require("fs");

const mergeValues = (values, content) => {
  //cycle over all the keys
  for(var key in values) {
    content = content.replace("{{" + key + "}}", values[key]);
  }
    //replace all {{key}} with the value from the values object
  return content;
};

const view = (templateName, values, response) => {
  //read from the template files
  let fileContents = fs.readFileSync(`./views/${templateName}.html`, {encoding: "utf8"});
  //insert values into the content
  fileContents = mergeValues(values, fileContents);
  //write out the content
  response.write(fileContents);
};

module.exports.view = view;

and my router.js:

const Profile = require("./profile.js");
const renderer = require("./renderer.js");
const querystring = require("querystring");

const commonHeader = {'Content-Type' : 'text/html'};

//Handle the HTTP route GET / and POST / i.e. Home
const home = (request, response) => {
  //if URL == "/" && GET
  if (request.url === "/") {
    if (request.method.toLowerCase() === "get") {
      //show search field
      response.writeHead('200', commonHeader);
      renderer.view('header', {}, response);
      renderer.view("search", {}, response);
      renderer.view("footer", {}, response);
      response.end();
    } else {
      //if URL == "/" && POST
        //get the post data
      request.on("data", (postBody) => {
        //extract from the data
        let query = querystring.parse(postBody.toString());
        //we need to redirect to localhost:8080/chalkers now
        response.writeHead(303, {"Location": "/" + query.username});
        response.end();
        //redirect to /:username
      });
    }
  }
};

//Handle the HTTP route GET /:username i.e. /chalkers or /tennysonhorn
const user = (request, response) => {
  //if URL == "/..."
  let username = request.url.replace("/", "");
  if (username.length > 0) {
    response.writeHead('200', commonHeader);
    renderer.view("header", {}, response);
    //get JSON from Treehouse
    let studentProfile = new Profile(username);
    //on "end"
    studentProfile.on("end", (profileJSON) => {
      //show profile

      //store the values we need
      let values = {
        avatarURL: profileJSON.gravatarURL,
        username: profileJSON.profile_name,
        badges: profileJSON.badges.length,
        javaScriptPoints: profileJSON.points.JavaScript,
      }
      //simple response
      renderer.view("profile", values, response);
      renderer.view("footer", {}, response);
      response.end();
    });

    //on "error"
    studentProfile.on("error", (error) => {
      //show error
      renderer.view("error", {errorMessage: error.message}, response);
      renderer.view("search", {}, response);
      renderer.view("footer", {}, response);
      response.end();
    });
  }
}

module.exports.home = home;
module.exports.user = user;

2 Answers

I know this is an old question, but I think this should fix the images not showing:

in your profileJSON values, profileJSON.gravatarURL needs to be profileJSON.gravatar_url

Not sure why it crashes though.

Emmanuel Molina
Emmanuel Molina
9,268 Points

_http_outgoing.js:636 nextTick(msg.socket[async_id_symbol] often mean you try to response.write after a response.end You should follow the path of your request and watch for that kind of mistake.