WHAT - NodeJS 基本使用

发布于:2024-06-13 ⋅ 阅读:(128) ⋅ 点赞:(0)

hello world

const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {

  console.log('server get request...');

  // http.IncomingMessage (in http.Server)
  // 获取 http 请求的正文数据
  // request 对象在这里是一个流 因此必须监听要处理的主体内容,并且其是按数据块处理的
  let data = '';
  req.on('data', (chunk) => {
    console.log(`可用的数据块: ${chunk}`);
    data += chunk;
  })
  req.on('end', () => {
    console.log('req end');
  })
  console.log('req method', req.method);
  console.log('req httpVersion', req.httpVersion);

  // http.ServerResponse
  res.statusCode = 200;
  // response.statusCode = 500
  // response.statusMessage = '内部服务器错误'
  res.setHeader('Content-Type', 'text/plain');
  console.log('res headers: ', res.getHeaderNames());

  res.end('Welcome');
})
server.listen(port, hostname, () => {

  console.log(`server running at http://${hostname}:${port}`);

  // process env
  // console.log('process env: ', process.env);
  
  // process argv
  process.argv.forEach((val, index) => {
    console.log(`${index}: ${val}`);
  })
  const args = process.argv.slice(2);
  // 1.
  // node app.js joe
  // console.log('user argvs: ', args[0]);
  // 2.
  // node app.js --name=joe
  // node app.js --name joe
  // const argsMap = require('minimist')(args)
  // console.log('user argvs: ', argsMap['name']);
})

// 使用进程信号句柄来终止
// process.on('SIGTERM', () => {
//   server.close();
// })
// setTimeout(() => {
//   process.kill(process.pid, 'SIGTERM');
// }, 3000);

http

参考阅读:http://dev.nodejs.cn/learn/the-nodejs-http-module

// 1. 属性
// http.METHODS
// http.STATUS_CODES
// http.globalAgent

// 2. 方法
// http.createServer()
// http.request()
// http.get()

// 3. 类
// http.Agent
// http.ClientRequest
// http.Server
// http.ServerResponse
// http.IncomingMessage (http.Server vs http.ClientRequest)

// 4. http.ServerResponse 与 http 消息头

// 4.1
// setHeader('headername', value) 设置 HTTP 消息头的值
// getHeaderNames() 获取已设置的 HTTP 消息头名称的列表
// getHeaders() 获取已设置的 HTTP 消息头的副本
// getHeader('headername') 获取已设置的 HTTP 消息头
// removeHeader('headername') 删除已设置的 HTTP 消息头
// hasHeader('headername') 如果响应已设置该消息头,则返回 true
// headersSent() 如果消息头已被发送给客户端,则返回 true

// 4. 2 writeHead vs write
// a. 在处理消息头之后,可以通过调用 response.writeHead()(该方法接受 statusCode 作为第一个参数,可选的状态消息和消息头对象)将它们发送给客户端。
// b. 若要在响应正文中发送数据给客户端,则使用 write()。 它会发送缓冲的数据到 HTTP 响应流。

// 5. http.IncomingMessage
// 5.1 使用 statusCode 和 statusMessage 方法来访问状态。
// 5.2 使用 headers 方法或 rawHeaders 来访问消息头。
// 5.3 使用 method 方法来访问 HTTP 方法。
// 5.4 使用 httpVersion 方法来访问 HTTP 版本。
// 5.5 使用 url 方法来访问 URL。
// 5.6 使用 socket 方法来访问底层的 socket。

http request

const https = require('https')

// get
const options = {
  hostname: 'nodejs.cn',
  port: 443,
  path: '/todos',
  method: 'GET', 
}
const req = https.request(options, res => {

  console.log(`状态码: ${res.statusCode}`)
  res.on('data', d => {
    process.stdout.write(d)
  })
})
req.on('error', error => {
  console.error(error)
})
req.end()

// post
const data = JSON.stringify({
  todo: '做点事情'
})
const optionsPost = {
  hostname: 'nodejs.cn',
  port: 443,
  path: '/todos',
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Content-Length': data.length
  }
}
const reqPost = https.request(optionsPost, res => {

  // http.IncomingMessage (in http.ClientRequest)
  console.log(`状态码: ${res.statusCode}`)

  // response.read() vs response.on('data')
  res.on('data', d => {
    process.stdout.write(d)
  })
})
reqPost.on('error', error => {
  console.error(error)
})
reqPost.write(data)
reqPost.end()

axios 版本

const axios = require('axios');

axios.post('http://localhost:3000', {
  todo: 'do something'
}).then(res => {

  console.log(`状态码: ${res.status}`)
  console.log(`Data: ${res.data}`)
  // console.log(res)
}).catch(error => {
  console.error(error)
})

events: EventEmitter

const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Welcome');
})
server.listen(port, hostname, () => {
  console.log(`server running at http://${hostname}:${port}`);
  
  const EventEmitter = require('events');
  const eventEmitter = new EventEmitter();

  // emit 触发

  // on 在事件被触发时执行
  // addListener

  // once

  // off
  // removeListener

  // removeAllListeners

  eventEmitter.on('start', (msg) => {
    console.log('start...', msg);
  })

  eventEmitter.emit('start', 'fuck')

  // 其他
  // emitter.getMaxListeners()
  // emitter.setMaxListeners()
  // emitter.prependListener()
  // emitter.prependOnceListener()
})

// 使用进程信号句柄来终止
process.on('SIGTERM', () => {
  server.close();
})
setTimeout(() => {
  process.kill(process.pid, 'SIGTERM');
}, 3000);

error catch

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Welcome');
})
server.listen(port, hostname, () => {

  // 1.
  try {
    //代码行
  } catch (e) {}

  // 2.
  // 如果在程序执行过程中引发了未捕获的异常,则程序会崩溃
  process.on('uncaughtException', err => {

    console.error('有一个未捕获的错误', err)
    process.exit(1)
  })

  // 3.
  // promise

  // 3.1 使用 promise 可以链接不同的操作,并在最后处理错误
  // .then().then().catch((err) => {})
  const doSomething1 = () => {

    return new Promise((resolve, reject) => {
      //...
      try {
        //...
        // x = y
  
        console.log('1');
        throw new Error('errxx1')
        resolve('hello1');
      } catch (err) {
        //... 在本地处理
        console.log('1-1');
        throw new Error(err.message)
      }
      //...
    })
  }
  const doSomething2 = () => {
  
    return new Promise((resolve, reject) => {
      //...
      try {
        //...
        // x = y
  
        console.log('2');
        throw new Error('errxx2')
        resolve('hello2');
      } catch (err) {
        //... 在本地处理
        throw new Error(err.message)
      }
      //...
    })
  }
  const doSomething3 = () => {
  
    return new Promise((resolve, reject) => {
      //...
      try {
        //...
        // x = y
  
        console.log('3');
        throw new Error('errxx3')
        resolve('hello3');
      } catch (err) {
        //... 在本地处理
        throw new Error(err.message)
      }
      //...
    })
  }
  doSomething1()
    .then(doSomething2)
    .then(doSomething3)
    .catch(err => console.error('after all then: ', err))

  // 3.2 为了能够在本地(而不是在调用的函数中)处理错误,则可以断开链条,在每个 then() 函数中创建函数并处理异常
  // doSomething1()
  //   .then(() => {
  //     return doSomething2().catch(err => {
  //       // 处理错误
  //       throw err // 打断链条
  //     })
  //   })
  //   .then(() => {
  //     return doSomething3().catch(err => {
  //       // 处理错误
  //       throw err // 打断链条
  //     })
  //   })
  //   .catch(err => console.error(err))

  // 4.
  // async/await
  // async function someFunction() {
  //   try {
  //     await someOtherFunction()
  //   } catch (err) {
  //     console.error(err.message)
  //   }
  // }


  console.log(`server running at http://${hostname}:${port}`);
})

// 使用进程信号句柄来终止
process.on('SIGTERM', () => {
  server.close();
})
setTimeout(() => {
  process.kill(process.pid, 'SIGTERM');
}, 3000);

console

const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Welcome');
})
server.listen(port, hostname, () => {
  console.log(`server running at http://${hostname}:${port}`);
  
  // 1.
  // http://dev.nodejs.cn/learn/output-to-the-command-line-using-nodejs
  console.log('我的%s已经%d岁', '猫', 2);
  // %s 格式化变量为字符串
  // %d 格式化变量为数字
  // %i 格式化变量为其整数部分
  // %o 格式化变量为对象

  // 2. 清空
  console.clear();

  // 3. 打印堆栈踪迹
  const function2 = () => console.trace()
  const function1 = () => function2()
  function1()

  // 4. 计算耗时
  const doSomething = () => console.log('测试')
  const measureDoingSomething = () => {

    console.time('doSomething()')
    doSomething()
    console.timeEnd('doSomething()')
  }
  measureDoingSomething()

  // 5. stdout vs stderr
  // console.log 在控制台打印消息就是所谓的标准输出
  // console.error 会打印到stderr流 不会出现在控制台 而是出现在错误日志中

  // 6. 着色
  // const chalk = require('chalk')
  // console.log(chalk.yellow('你好'))

  // 7. 进度条
  // const ProgressBar = require('progress')
  // const bar = new ProgressBar(':bar', { total: 10 })
  // const timer = setInterval(() => {
  //   bar.tick()
  //   if (bar.complete) {
  //     clearInterval(timer)
  //   }
  // }, 100)

  // 8. 对象
  const obj = {
    name: '1',
    age: 2
  }
  console.log(obj);
  // 在 Node.js 中会获得对象的字符串表示形式
  // 但是在经过两个级别的嵌套后,Node.js 会放弃并打印 [Object] 作为占位符
  const objHigh = {
    name: 'joe',
    age: 35,
    person1: {
      name: 'Tony',
      age: 50,
      person2: {
        name: 'Albert',
        age: 21,
        person3: {
          name: 'Peter',
          age: 23
        }
      }
    }
  }
  console.log(objHigh)
  // 推荐 (2 为缩进)
  console.log(JSON.stringify(objHigh, null, 2))
})

// 使用进程信号句柄来终止
process.on('SIGTERM', () => {
  server.close();
})
setTimeout(() => {
  process.kill(process.pid, 'SIGTERM');
}, 3000);

NODE_ENV

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Welcome');
})
server.listen(port, hostname, () => {
  
  // NODE_ENV=production node app.js
  console.log('env', process.env.NODE_ENV);

  if (process.env.NODE_ENV === "development") {
    //...
    console.log('111');
  }
  if (process.env.NODE_ENV === "production") {
    //...
    console.log('222');
  }
  if(['production', 'staging'].indexOf(process.env.NODE_ENV) >= 0) {
    //...
    console.log('333');
  }

  console.log(`server running at http://${hostname}:${port}`);
})

// 使用进程信号句柄来终止
process.on('SIGTERM', () => {
  server.close();
})
setTimeout(() => {
  process.kill(process.pid, 'SIGTERM');
}, 3000);

buffer

// http://dev.nodejs.cn/learn/nodejs-buffers

const http = require('http');
const fs = require('fs');
const path = require('path');

const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Welcome');
})
server.listen(port, hostname, () => {
  
  // path
  const fsPath = path.resolve(__dirname, './package.json');

  console.log(`server running at http://${hostname}:${port}`);
})

// 使用进程信号句柄来终止
process.on('SIGTERM', () => {
  server.close();
})
setTimeout(() => {
  process.kill(process.pid, 'SIGTERM');
}, 3000);

file

file open

const http = require('http');
const fs = require('fs');
const path = require('path');

const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Welcome');
})
server.listen(port, hostname, () => {
  
  const fsPath = path.resolve(__dirname, './package.json');
  console.log('fs path', fsPath);

  // fs.openSync vs fs.open
  fs.open(fsPath, 'r', (err, fd) => {

    console.log('文件描述符:', fd);
  })
  // r 打开文件用于读取
  // r+ 打开文件用于读写
  // w+ 打开文件用于读写,将流定位到文件的开头。如果文件不存在则创建文件
  // a 打开文件用于写入,将流定位到文件的末尾。如果文件不存在则创建文件
  // a+ 打开文件用于读写,将流定位到文件的末尾。如果文件不存在则创建文件


  // fs.statSync vs fs.stat
  fs.stat(fsPath, 'r', (err, stats) => {

    // console.log('文件属性:', stats);
    console.log('isFile: ', stats.isFile());
    console.log('isDirectory: ', stats.isDirectory());
    console.log('isSymbolicLink: ', stats.isSymbolicLink());
    console.log('size: ', stats.size);

  })


  console.log(`server running at http://${hostname}:${port}`);
})

// 使用进程信号句柄来终止
process.on('SIGTERM', () => {
  server.close();
})
setTimeout(() => {
  process.kill(process.pid, 'SIGTERM');
}, 3000);

file path

const http = require('http');
const fs = require('fs');
const path = require('path');

const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Welcome');
})
server.listen(port, hostname, () => {
  
  // path
  const fsPath = path.resolve(__dirname, './package.json');
  console.log('fs path: ', fsPath);
  console.log('dirname: ', path.dirname(fsPath));
  console.log('basename: ', path.basename(fsPath));
  console.log('extname: ', path.extname(fsPath));
  console.log('basename without extname: ', path.basename(fsPath, path.extname(fsPath)));

  // path.join vs path.resolve
  
    // join 连接路径的两个或多个片段
  const name = 'joe'
  console.log(path.join('/', 'users', name, 'notes.txt')); 

    // resolve 获得相对路径的绝对路径计算
  console.log(path.resolve('package.json'));

  console.log(path.resolve('joe.txt'));
  console.log(path.resolve('tmp', 'joe.txt'));
  console.log(path.resolve('/tmp', 'joe.txt'));

  // path.normalize
  console.log(path.normalize('/users/joe/..//test.txt'));

  // 其他
  // path.isAbsolute()
  // path.parse()
  // path.relative()

  console.log(`server running at http://${hostname}:${port}`);
})

// 使用进程信号句柄来终止
process.on('SIGTERM', () => {
  server.close();
})
setTimeout(() => {
  process.kill(process.pid, 'SIGTERM');
}, 3000);

file read and write

const http = require('http');
const fs = require('fs');
const path = require('path');

const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
  
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Welcome');
})
server.listen(port, hostname, () => {
  
  const fsPath = path.resolve(__dirname, './package.json');
  console.log('fs path', fsPath);

  // 1.读
  // fs.readFile vs fs.readFileSync
  fs.readFile(fsPath, 'utf8', (err, data) => {

    if (err) {
      console.error(err)
      return
    }
    console.log(data)
  })

  // 注意 fs.readFile() 和 fs.readFileSync() 都会在返回数据之前将文件的全部内容读取到内存中。
  // 这意味着大文件会对内存的消耗和程序执行的速度产生重大的影响。
  // 在这种情况下,更好的选择是使用流来读取文件的内容。

  // 2.写
  // 同理
  // fs.writeFile vs fs.writeFileSync
  // fs.appendFile vs fs.appendFileSync
  // 注意 所有这些方法都是在将全部内容写入文件之后才会将控制权返回给程序(在异步的版本中,这意味着执行回调)。
  // 在这种情况下,更好的选择是使用流写入文件的内容。

  // 3.流
  // stream

  console.log(`server running at http://${hostname}:${port}`);
})

// 使用进程信号句柄来终止
process.on('SIGTERM', () => {
  server.close();
})
setTimeout(() => {
  process.kill(process.pid, 'SIGTERM');
}, 3000);

stream

// http://dev.nodejs.cn/learn/nodejs-streams
// 1. 读/写文件
// 2. 网络通信
// 3. 任何类型的端到端的信息交换

const http = require('http');
const fs = require('fs');
const path = require('path');

const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
 
  // fs.createReadStream() 创建文件的可读流
  const fsPath = path.resolve(__dirname, './package.json');
  console.log('path: ', fsPath);
  const stream = fs.createReadStream(fsPath);
  // console.log(stream);
  // stream.pipe(res);

  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Welcome');
})
server.listen(port, hostname, () => {

  console.log(`server running at http://${hostname}:${port}`);
})

// 使用进程信号句柄来终止
// process.on('SIGTERM', () => {
//   server.close();
// })
// setTimeout(() => {
//   process.kill(process.pid, 'SIGTERM');
// }, 3000);

os

const http = require('http');

const os = require('os')

const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Welcome');
})
server.listen(port, hostname, () => {
  
  console.log(`server running at http://${hostname}:${port}`);

  // console.log(os.EOL);
  // console.log(os.constants.signals);
  // console.log(os.constants.errno);

  console.log(os.arch());
  // console.log(os.cpus());
  // console.log(os.endianness());
  // console.log(os.freemem());
  // console.log(os.homedir());
  console.log(os.hostname());
  // console.log(os.loadavg());
  // console.log(os.networkInterfaces());
  console.log(os.platform());
  console.log(os.release());
  // console.log(os.tmpdir());
  // console.log(os.totalmem());
  console.log(os.type());
  console.log(os.uptime());
  console.log(os.userInfo());


})

// 使用进程信号句柄来终止
process.on('SIGTERM', () => {
  server.close();
})
setTimeout(() => {
  process.kill(process.pid, 'SIGTERM');
}, 3000);

网站公告

今日签到

点亮在社区的每一天
去签到