Node.js几道面试题

一些声明

经过这些问题就来判断一我的的Node.js水平是不太严谨的,可是它能让你对面试者在Node.js上的经验如何有个大概的了解。面试

可是显然,这些问题并不会告诉你面试者思考问题的方式。npm

Show me the code. 结合一些编程题来考察面试者吧编程

你们都是人,不要作一个死板不近人情的面试官哦。api


什么是error-first的回调方式

Error-first回调方式用来同时传递error和data。将错误做为第一个参数,它就必须先检查看看有没有错误先。另外的参数就用来传递data了。浏览器

fs.readFile(filePath, function(err, data) {
  if(err) {
    //处理错误,这里的return很重要,若是发生错误,在此处就会中止了。
    return console.log(err);
  }
  //传递data
  console.log(data);
})

你是如何避免回调地狱的?

  • 模块化 把回调函数分割成独立的函数安全

  • 使用控制流的库,好比asynccookie

  • generators结合Promise异步

  • async/awaitasync


Promise是什么?

概念很少说了,简单来讲就是帮助你更好地处理异步操做的东西。模块化

new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('result');
  }, 100)
})
  .then(console.log)
  .catch(console.error)

stub是什么? 举个例子?

stub是用来模拟组件/模块行为的东西,它在测试阶段为函数调用提供内部响应。

例子是写文件,但实际上并无这么作

var fs = require('fs');

var writeFileStub = sinon.stub(fs, 'writeFile', function(path, data, cb) {
  return cb(null)
})

expect(writeFileStub).to.be.called
writeFileStub.restore();

如何保证你的HTTP cookies安全不受XSS攻击

set-cookieHTTP头部加上这几个信息:

  • HttpOnly-这个属性用来防止跨站脚本攻击,它不容许cookie被JavaScript代码获取。

  • secure-这个属性告诉浏览器只有在HTTPS链接时才发送cookie

像这样:Set-Cookit: sid=<cookit-value>; HttpOnly


下面这段代码有什么问题

new Promise((resolve, reject) => {
  throw new Error('error')
}).then(console.log)

then后面没有跟上catch,这样的话若是出错的这段代码仍是默默地运行,并不会告诉你哪里出错了。

修改后:

new Promise((resolve, reject) => {
  throw new Error('error')
}).then(console.log).catch(console.error)

若是你正在调试一个大型项目,你不知道哪一个Promise可能会有问题,可使用unhandledRejection。它会打印出全部未经处理的Promise异常

process.on('unhandledRejection', (err) => {
  console.log(err)
})

下面的代码有什么问题?

function checkApiKey(apiKeyFromDb, apiKeyReceived) {
  if (apiKeyFromDb === apiKeyReceived) {
    return true
  }
  return false
}

说实话我刚看到的时候也是一脸懵逼,这有啥问题?不是很正常的一个if else代码吗。

不过这不是普通的if else代码,这是用来比较安全证书的代码,这个时候你不能泄露一丁点的信息,因此确保他们在必定的时间内进行比较。不然的你的应用就可能受到时序攻击了。

什么是时序攻击(timing attacks)?Node.js使用的V8引擎试图从表示层面上优化代码。它一个字符一个字符地比较,一旦找到不符合它就中止比较。

你可使用cryptiles这个npm模块来解决这个问题

function checkApiKey(apiKeyFromDb, apiKeyReceived) {
  return cryptiles.fixedTimeCimparison(apiKeyFromDb, apiKeyReceived)
}

某乎上有个解释地挺好的如何通俗地解释时序攻击(timing attack)?


下面的代码会输出什么

Promise.reso(1)
  .then((x) => x + 1)
  .then((x) => {throw new Error('My Error')})
  .catch(() => 1)
  .then((x) => x + 1)
  .then((x) => console.log(x))
  .catch(console.error)
  1. 一个新的Promise被创造出来,它会解析参数1

  2. 解析后的值会被加上1(如今是2),并当即返回了这个2

  3. 解析的值被丢弃,抛出一个异常

  4. 异常被丢弃,新的值1被返回

  5. catch后运行不会中止,在异常处理以前,它继续运行,一个新的,增长了1后的值2被返回

  6. 返回值被打印出来

  7. 这一行不会运行,由于没有异常