Skip to content

Instantly share code, notes, and snippets.

@subfuzion
Last active March 19, 2021 10:03
Show Gist options
  • Save subfuzion/62a00f57cce0ddcd6cc608aa59fdc514 to your computer and use it in GitHub Desktop.
Save subfuzion/62a00f57cce0ddcd6cc608aa59fdc514 to your computer and use it in GitHub Desktop.
Node.js Assessment

A few questions for quickly assessing candidate's Node.js skill level

  1. Write a function that simulates an asynchronous I/O function call. The function should be called ping. It should accept one argument called delay that will determine how many seconds before the function will call back with a response (pong). If no argument is provided, it should call back immediately. If the argument is greater than 3, it should call back with an error.
function ping(delay, callback) {
 // if delay is not provided, it should default to 0
 if (typeof delay === 'function') {
   callback = delay;
   delay = 0;
 }
   
 try {
   delay = parseInt(delay, 10);
   if (delay > 3) {
     setImmediate(function() {
       // MUST call back asynchronously
       callback(new Error('delay value > 3: ' + delay));
     })
   } else {
     setTimeout(function() {
       callback(null, 'pong');
     }, delay * 1000);
   }
 } catch (err) {
   // MUST call back asynchronously
   setImmediate(function() {
     callback(err);
   });
 }
}
  1. Print an array of numbers to the console without using a loop
[ 1, 2, 3 ].forEach(function(n) {
  console.log(n);
});
  1. Use the functional approach to converting an array of numbers to an array of the squares of the numbers ([1,2,3] -> [1,4,9])
var squares = [ 1, 2, 3 ].map(function(n) {
  return n * n;
});
  1. Using the ping async function we created earlier, take an array of delay values and invoke the ping function using the async library and print each result.

Note: it's ok if candidate is not familiar with async library if the candidate at least could either implement something reasonable for chaining callbacks, or has already been using promises or async/await and can come up with something reasonable based on that. The candidate would have to understand how to promisify the ping function, or at the very least be familiar with promisifying it using a library like bluebird.

async.each([1, 2, 3], ping, function(result, callback) {
  console.log(result);
  callback();
}, function(err) {
  if (err) {
    console.log(err);
  } else {
    console.log('done');
  }
});

For example, with async/await...

let pingAsync = bluebird.promisify(ping)

[1, 2, 3].forEach(n => {
  try {
    let result = await pingAsync(n)
    console.log(`${n} -> ${result}`)
  } catch (err) {
    console.log(`error: ${n} -> ${err.message}`)
  }
})
  1. Discuss scope in JavaScript

Candidate should discuss function scope

Candidate should understand hoisting.

Extra points if candidate can discuss ES6 block scope, and let and const keyword (as opposed to var).

  1. Discuss apply, call, bind, and this context.
  • use apply on a function that expects a number of arguments when you have an array: func.apply(thisArg, [arrayLikeObject])

Candidate should be able to note that the arrayLikeObject simply means any object that has a length property (such as arguments automatic local variable).

  • call is like apply, except you provide an argument list instead of a single array-like object: func.call(thisArg[, arg1, ...])

  • bind is used on a function to return a new function that wraps it, using the this value that was provide to set the function's this context: var f = func.bind(thisArg[, arg1, ...])

Note that the optional arguments will be prepended to the argument list when actually invoking the newly returned function.

Candidate should be able to explain how using bind is an alternative to storing the this context before invoking a function that will callback, where in the callback you need to have access to the correct context. For example, many developers will write var that = this so that they can use that in a callback. With bind, it is unnecessary to save this in another variable.

  1. Describe the Node.js concurrency model

Looking to hear candidate mention things about:

asynchronous non-blocking i/o event-driven / event loop callbacks

single threaded model from programmer perspective; async work happens in callbacks, which run until completion (which might possibly include making other requests that will have callbacks run at some point in the future)

Extra points if candidate contrasts against and explains disadvantages of thread-based concurrency model:

threaded code execution paths can be difficult to reason through

synchronized access to shared state is error prone, can be difficult to debug issues, errors can be non-deterministic (race conditions)

threads are relatively inefficent compared to callbacks (stack allocation, context switches)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment