node基础

243 阅读7分钟

目录

  1. node简介
  2. 一点历史
  3. 优缺点
  4. node的模块
  5. API学习
  6. 案例
  7. 最后

node简介

  1. Node.js 是一个开源与跨平台的 JavaScript 运行时环境。 它是一个可用于几乎任何项目的流行工具!
  2. Node.js 应用程序运行于单个进程中,无需为每个请求创建新的线程。 Node.js 在其标准库中提供了一组异步的 I/O 原生功能(用以防止 JavaScript 代码被阻塞),并且 Node.js 中的库通常是使用非阻塞的范式编写的(从而使阻塞行为成为例外而不是规范)
  3. Node.js 具有独特的优势,因为为浏览器编写 JavaScript 的数百万前端开发者现在除了客户端代码之外还可以编写服务器端代码,而无需学习完全不同的语言。

3472BB7719B5C6980FE510AF4D9ADBB9.jpg

一点历史

  1. JavaScript 是一门被创建于 Netscape(作为用于在其浏览器 Netscape Navigator 中操纵网页的脚本工具)中的编程语言。
  2. 随着许多浏览器竞相为用户提供最佳的性能,JavaScript 引擎也变得更好。 主流浏览器背后的开发团队都在努力为 JavaScript 提供更好的支持,并找出使 JavaScript 运行更快的方法。 多亏这场竞争,Node.js 使用的 V8 引擎(也称为 Chrome V8,是 Chromium 项目开源的 JavaScript 引擎)获得了显着的改进
  3. V8 是为 Google Chrome 提供支持的 JavaScript 引擎的名称。 当使用 Chrome 进行浏览时,它负责处理并执行 JavaScript。
  4. 很酷的是,JavaScript 引擎独立于托管它的浏览器。 此关键的特性推动了 Node.js 的兴起。 V8 于 2009 年被选为为 Node.js 提供支持的引擎,并且随着 Node.js 的爆炸性发展,V8 成为了现在为大量的服务器端代码(使用 JavaScript 编写)提供支持的引擎。

优缺点

优点

  1. 便于前端开发,node是js为基础
  2. 性能高,node比php快八九十杯,运行在chrome v8引擎上;
  3. 利于前端代码整合

####缺点 比较新,缺少框架,比java等其他服务端语言的框架量差别巨大

node的模块

全局模块

node包含一些全局变量,无需使用 require()就可以直接使用

  • __dirname 表示当前执行脚本所在的目录。
  • __filename 表示当前正在执行的脚本的文件名
  • process 描述当前Node.js 进程状态的对象

系统模块

  • path 用于处理文件路径和目录路径的使用工具
  • fs 用于文件读写操作
  • http 网络处理

API学习

http模块

通过http模块启动一个简单的服务,打印出来数据到页面,需要注意的是请求返回类型处理,了解res.whiteHead设置,熟悉一下res的API

// 1. 引入 http 模块
var http = require("http");

// 2. 用 http 模块创建服务
/**
 * req 获取 url 信息 (request)
 * res 浏览器返回响应信息 (response)
 */
http.createServer(function (req, res) {
  // 设置 HTTP 头部,状态码是 200,文件类型是 html,字符集是 utf8
  res.writeHead(200, {
    "Content-Type": "text/html;charset=UTF-8"
  });

  // 往页面打印值
  res.write('<h1 style="text-align:center">Hello NodeJS</h1>');

  // 结束响应
  res.end();

}).listen(3000); // 监听的端口

URL 模块

url模块主要是对获取的url进行解析和处理

  • url 模块所有内容:
const url = require("url");
console.log(url);
/**
 * Console:
 { 
   Url: [Function: Url],
    parse: [Function: urlParse], // 获取地址信息
    resolve: [Function: urlResolve], // 追加或者替换地址
    resolveObject: [Function: urlResolveObject],
    format: [Function: urlFormat], // 逆向 parse,根据地址信息获取原 url 信息
    URL: [Function: URL],
    URLSearchParams: [Function: URLSearchParams],
    domainToASCII: [Function: domainToASCII],
    domainToUnicode: [Function: domainToUnicode] 
  }
 */
  • parse 如何使用
/**
 * parse 方法需要两个参数:
 * 第一个参数是地址
 * 第二个参数是 true 的话表示把 get 传值转换成对象
 */ 
// console.log(url.parse("http://www.baidu.com/new?name=zhangsan", true));
  • format 的使用:
console.log(url.format({
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'www.baidu.com',
  port: null,
  hostname: 'www.baidu.com',
  hash: null,
  search: '?name=zhangsan',
  query: 'name=zhangsan',
  pathname: '/new',
  path: '/new?name=zhangsan',
  href: 'http://www.baidu.com/new?name=zhangsan' 
}))

// Console:
// http://www.baidu.com/new?name=zhangsan
  • resolve 的使用:
console.log(url.resolve("http://www.baidu.com/qiaozhi", "node"));

// Console:
// http://www.baidu.com/node

fs 文件管理

fs模块主要对文件的一些处理,检查、创建、删除、读取、写入等;

  • fs.stat 检查一个读取的是文件还是目录
let fs = require('fs');
fs.stat('fs/index.js', (error, stats) => {
  if(error) {
    console.log(error);
    return false;
  } else {
    console.log(stats);
    console.log(`文件:${stats.isFile()}`); 
    // Console:文件:true
   
    console.log(`目录:${stats.isDirectory()}`); 
    // Console:目录:false

    return false;
  }
})
  • fs.mkdir 创建目录
let fs = require('fs');

/**
 * 接收参数
 * path - 将创建的目录路径
 * mode - 目录权限(读写权限),默认 0777
 * callback - 回调,传递异常参数 err
 */
fs.mkdir('fs/css', (err) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    console.log("创建目录成功!");
  }
})
  • fs.rmdir 删除目录:
let fs = require('fs');

/**
 * 接收参数
 * path - 将删除的目录路径
 * mode - 目录权限(读写权限),默认 0777
 * callback - 回调,传递异常参数 err
 */
fs.rmdir('fs/css', (err) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    console.log("删除目录成功!");
  }
})

  • fs.writeFile 写入文件
let fs = require('fs');

/**
 * filename (String) 文件名称
 * data (String | Buffer) 将要写入的内容,可以是字符串或者 buffer 数据。
 * · encoding (String) 可选。默认 'utf-8',当 data 是 buffer 时,该值应该为 ignored。
 * · mode (Number) 文件读写权限,默认 438。
 * · flag (String) 默认值 'w'。
 * callback { Function } 回调,传递一个异常参数 err。
 */
fs.writeFile('fs/write-file.js', 'writeFile', (err) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    console.log('写入成功!');
  }
})
  • fs.appendFile: 追加文件内容
let fs = require('fs');

fs.appendFile('fs/write-file.js', '这段文本是要追加的内容', (err) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    console.log("追加成功");
  }
})
  • fs.readFile 读取文件
let fs = require('fs');

fs.readFile('index.js', (err, data) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    console.log("读取文件成功!");
    console.log(data);
    console.log(data.toString());
  }
})
  • fs.readdir 读取目录
let fs = require('fs');
fs.readdir('fs', (err, data) => {
  if(err) {
    console.log(err);
    return false;
  } else {
    console.log("读取目录成功!");
    console.log(data);
  }
})

案例

创建 Web 服务器

在这里,我们利用 http 模块、url 模块、path 模块、fs 模块创建一个 Web 服务器。

 什么是 Web 服务器?  Web 服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以像浏览器等 Web 客户端提供文档,也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载。目前最主流的三个 Web 服务器是 Apache、Nginx、IIS。

// 引入 http 模块
let http = require("http");

// 引入 fs 模块
let fs = require("fs");

// 引入 url 模块
let url = require("url");

// 引入 path 模块
let path = require("path");

http.createServer((req, res) => {
  
  // 获取响应路径
  let pathName = url.parse(req.url).pathname;

  // 默认加载路径
  if (pathName == "/") {
    // 默认加载的首页
    pathName = "index.html";
  }
  // 获取文件的后缀名
  let extName = path.extname(pathName);

  // 过滤 /favicon.ico 的请求
  if (pathName != "/favicon.ico") {
    // 获取 08_WebService 下的 index.html
    fs.readFile("./web-service/" + pathName, (err, data) => {
      // 如果不存在这个文件
      if (err) {
        console.log("404 Not Found!");
        fs.readFile(
          "./web-service/404.html",
          (errorNotFound, dataNotFound) => {
            if (errorNotFound) {
              console.log(errorNotFound);
            } else {
              res.writeHead(200, {
                "Content-Type": "text/html; charset='utf-8'"
              });
              // 读取写入文件
              res.write(dataNotFound);
              // 结束响应
              res.end();
            }
          }
        );
        return;
      }
      // 返回这个文件
      else {
        // 获取文件类型
        let ext = getExt(extName);

        // 设置请求头
        // res.writeHead(200, {
        //   "Content-Type": ext + "; charset='utf-8'"
        // });
        //  不设置其他文件格式
        res.writeHead(200, {
          "Content-Type": "text/html; charset='utf-8'"
        });
        // 读取写入文件
        res.write(data);
        // 结束响应
        res.end();
      }
    });
  }
}).listen(3000);

// 获取后缀名
getExt = (extName) => {
  switch(extName) {
    case '.html': return 'text/html';
    case '.css': return 'text/css';
    case '.js': return 'text/js';
    default: return 'text/html';
  }
}

实现注册、登录

通过以上学习的API和实例,来实现一个简单的注册登录接口,便于大家更好理解服务端开发,进而扩展前端的视野;

const http = require('http');
const url = require('url');
const fs = require('fs');
// 查找字符串
const querystring = require('querystring');
const users = [{
  username: '乔治',
  password: 123
}];

http.createServer((req, res)=>{
  
  let {pathname, query} = url.parse(req.url, true);
  // 设置跨域的域名,* 代表允许任意域名跨域
  res.setHeader('Access-Control-Allow-Origin', '*');
  // 设置 header 类型
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
  // 跨域允许的请求方式
  res.setHeader('Content-Type', 'application/json');
  if(req.method == 'GET') {
    if(pathname == '/login'){
      req.statusCode = 200;
      // 查找用户
      const user = findUser(query);
      if(user.username == query.username){
        if(user.password == query.password){
          // 数据必须JSON.stringify处理,否则会报错
          res.end(JSON.stringify({
            err: 0,
            msg: '登录成功'
          }))
        } else {
          res.end(JSON.stringify({
            err: 2,
            msg: '密码错误'
          }))
        }
      } else{
        res.end(JSON.stringify({
          err: 1,
          msg: '用户不存在'
        }))
      }
    } else {
      // 创建web服务器
      createWebService(req,res,pathname);
    }
  }else if(req.method == 'POST'){
    req.statusCode = 200;
    const arr = [];
    req.on('data',(buffer)=>{
      arr.push(buffer);
    })
    req.on('end', ()=>{
      // 获取请求的参数对象
      const result = querystring.parse(Buffer.concat(arr).toString());
      const user = findUser(result);
      if(user.username){
        res.end(JSON.stringify({
          err: 3,
          msg: '用户已存在'
        }))
      }else{
        users.push(result);
        res.end(JSON.stringify({
          err: 0,
          msg: '用户注册成功'
        }))
      }
    })
  }
  
}).listen(3000);

// 创建web服务器
const createWebService = function(req,res,pathName){
  // 默认加载路径
  if(pathName == '/'){
    pathName = 'index.html';
  }
  if(pathName !== "/favicon.ico"){
    fs.readFile('./login/'+pathName, (err, data)=>{
      if(err){
        console.log(err);
      } else {
        res.writeHead(200, {
          "Content-Type": "text/html; charset='utf-8'"
        })
        res.write(data);
        res.end();
      }
    })
  }
}
// 获取用户
const findUser = function(user){
  return users.filter(item=>{
    return item.username == user.username;
  })[0] || {};
}

最后

继续学习node基础的同时了解一些node的框架,以下列举最近排名靠前的四个框架,仅供参考

  • express :star和下载量最高的老牌框架
  • koa :express 的继任者
  • nest :增长最快的框架
  • egg :阿里开源的node.js框架

QQ20210524-093127@2x.png