• Node.js实用知识点


    本文介绍如何使用nodejs

    简单的HttpServer

    创建一个app.js文件输入如下内容
        const http = require('http');
    
        http.createServer((req,res) => {
            res.writeHead(200, {
                'Content-Type': 'text/plain'
            }) 
    
            res.write('Hello, World!
    '); // 返回给客户端的消息
    
            res.end();
        }).listen(8000);
    
    用浏览器访问http://localhost:8000/即可
    

    调试nodejs

    运行 node --inspect-brk app.js
    然后在你的程序里面随便写个断点debugger
    使用谷歌访问about://inspect,然后点击inspect进入你的程序
    使用前端访问,即可进入刚才打的断点即可
    

    基础路由

    1. 回调函数形式

      const http = require('http');
      
      function index(req, res) {
          res.writeHead(200);
          res.end('Hello, World!');
      }
      
      http.createServer(function(req,res){
          res.setHeader("Access-Control-Allow-Origin","*");
          res.setHeader("Access-Control-Allow-Headers","content-type");
          res.setHeader("Access-Control-Allow-Methods","DELETE,PUT,POST,GET,OPTIONS");
          
          if(req.url === '/') {
              return index(req, res);
          }
      
          res.writeHead(404);
          res.end(http.STATUS_CODES[404]);
      }).listen(8000)
      
    2. 对象形式

      const http = require('http');
      var routes = {
          '/': function index(req, res) {
              res.writeHead(200);
              res.end('Hello, World');
          },
          '/test': function test(req, res) {
              res.writeHead(200);
              res.end("test page");
          }
      }
      
      http.createServer(function(req,res){
          res.setHeader("Access-Control-Allow-Origin","*");
          res.setHeader("Access-Control-Allow-Headers","content-type");
          res.setHeader("Access-Control-Allow-Methods","DELETE,PUT,POST,GET,OPTIONS");
          
          if(req.url in routes) {
              return routes[req.url](req, res)
          }
      
          res.writeHead(404);
          res.end(http.STATUS_CODES[404]);
      }).listen(8000)
      

    nodejs配置开发和生产环境

    1. 项目目录

    2. development.js

      module.exports={
          args: {
              a: 'development'
          }
      }
      
    3. production.js

      module.exports={
          args: {
              a: 'production'
          }
      }
      
    4. config.js

      var path = require('path');
      var env = process.env.NODE_ENV || 'production';
      env=env.toLowerCase();
      
      var file = path.resolve(__dirname, env);
      
      try{
          module.exports = require(file+'.js');
      }catch(err) {
          throw err;
      }
      
    5. app.js

      const http = require('http');
      
      var args = require('./config/config.js');
      console.log(args.args.a);
      
      var routes = {
          '/': function index(req, res) {
              res.writeHead(200);
              res.end('Hello, World');
          },
          '/test': function test(req, res) {
              res.writeHead(200);
              res.end("test page");
          }
      }
      
      http.createServer(function(req,res){
          res.setHeader("Access-Control-Allow-Origin","*");
          res.setHeader("Access-Control-Allow-Headers","content-type");
          res.setHeader("Access-Control-Allow-Methods","DELETE,PUT,POST,GET,OPTIONS");
          
          if(req.url in routes) {
              return routes[req.url](req, res)
          }
      
          res.writeHead(404);
          res.end(http.STATUS_CODES[404]);
      }).listen(process.env.PORT || 8001)
      
    6. 运行

      set NODE_ENV=development&&set PORT=8881&&node app.js
      

    nodejs核心模块一览

    'assert' 断言测试模块
    'buffer' 操作二进制数据
    'c/c++_addons' 提供在js中运行c/c++库接口
    'child_process' 生成子进程
    'cluster' 利用此模块可以把nodejs集群进程部署在同一端口的多核计算机上
    'console' 提供一个console功能,类似浏览器的
    'crypto' 提供加密功能
    'deprecated_apis' 废弃的api
    'dns' 通过dns.lookup()访问本机的dns,通过提供的其他api访问网络dns
    'domain' 弃用了
    'Events' 异步事件驱动架构
    'fs' 文件I/O操作
    'http' 方便操作http协议
    'https' 方便操作https协议
    'module' 文件加载系统
    'net' 异步网络包装器
    'os' 提供操作系统api接口
    'path' 提供工具操作文件和文件夹路径
    'punycode' 废弃
    'querystring' 提供工具转化和格式化URL查询字符串
    'readline' 提供接口用来从可读流中读取数据一次一行,例如process.stdin
    'repl' 提供一个REPL实现
    'stream' 操作流对象
    'string_decoder' 提供api用来解码Buffer对象转化成字符串
    'timers' 提供全局api用来执行定时任务
    'tls_(ssl)' 提供api用来实现OpenSSL
    'tracing' 用来追踪程序中产生的信息,添加--trace-events-enabled开启
    'tty' 几乎没啥用
    'dgram' 提供实现UDP数据报
    'url' 提供api操作URL
    'util' node.js的内部api
    'v8' 提供v8api
    'vm' 提供api在v8虚拟环境中编译和运行js
    'zlib' 提供实现Gzip的函数接口
    

    express用法

    1. 路由方法处理

      npm install express --save
      
      const express = require('express');
      const app = express();
      const port = 8000;
      
      app.all("*",function(req,res,next){
          // 所有路由
          res.header("Access-Control-Allow-Origin","*");
          res.header("Access-Control-Allow-Headers","content-type");
          res.header("Access-Control-Allow-Methods","DELETE,PUT,POST,GET,OPTIONS");
          if (req.method.toLowerCase() == 'options') res.send(200);  
          else next();
      });
      
      app.get("/testget", function(req, res, next){
          res.send('testget');
      })
      
      app.post("/testpost", function(req, res, next){
          res.send('testpost');
      })
      
      app.put("/testput", function(req, res, next){
          res.send('testput');
      })
      
      app.delete("/testdelete", function(req, res, next){
          res.send('testdelete');
      })
      
      app.use("/testuse", function(req, res, next){
          // 所有路由
          res.send('testuse');
      })
      
      // 路由链
      app.route('/testroute').get(function (req, res, next) {
          res.send('testrouteget');
      }).post(function (req, res, next) {
          res.send('testroutepost');
      }).put(function (req, res, next) {
          res.send('testrouteput');
      })
      
      
      // 函数链
      app.get('/mypath', function (req, res, next) {
          console.log('1');
          next();
      }, function (req, res, next) {
          console.log('2');
          res.send('....');
      })
      
      app.listen(port, function() {
          console.log('Server listening on http://localhost:' + port);
      });
      
    2. 模块化(直接传递值)

      app.js
          const express = require('express');
          const otherMiddleware = require('./other.js');
          const app = express();
      
          app.all("*",function(req,res,next){
              // 所有路由
              res.header("Access-Control-Allow-Origin","*");
              res.header("Access-Control-Allow-Headers","content-type");
              res.header("Access-Control-Allow-Methods","DELETE,PUT,POST,GET,OPTIONS");
              if (req.method.toLowerCase() == 'options') res.send(200);  
              else next();
          });
      
          app.use('/api/v1/', otherMiddleware({ data:'Hello world' })).listen(8000);
      
      other.js
          const express = require('express');
          module.exports = function(options={}){
              const router = express.Router();
      
              router.get('/test', (req, res, next) => {
                  res.end(options.data);
              })
      
              return router;
          }
      
    3. 模块化(传递类实例)

      app.js
          const express = require('express');
          const otherMiddleware = require('./other.js');
          const app = express();
      
          app.all("*",function(req,res,next){
              // 所有路由
              res.header("Access-Control-Allow-Origin","*");
              res.header("Access-Control-Allow-Headers","content-type");
              res.header("Access-Control-Allow-Methods","DELETE,PUT,POST,GET,OPTIONS");
              if (req.method.toLowerCase() == 'options') res.send(200);  
              else next();
          });
      
          class CreateDataService {
              constructor(data='Hello'){
                  this.data=data;
              }
      
              createData(outdata) {
                  return `${this.data}, ${outdata}!`;
              }
          }
      
          app
              .use('/api/v1/service1', otherMiddleware({ service: new CreateDataService('Hello')}))
              .use('/api/v1/service2', otherMiddleware({ service: new CreateDataService('Hi')}))
              .listen(8000);
      
      other.js
          const express = require('express');
      
          module.exports = function(options={}){
              const router = express.Router();
      
              const {service} = options;
      
              router.get('/test', (req, res, next) => {
                  res.end(service.createData(req.query.outdata || "haven't any data"));
              })
      
              return router;
          }
      
      请求 
          http://localhost:8000/api/v1/service1/test?outdata=World
          http://localhost:8000/api/v1/service2/test?outdata=World
      
    4. 模板引擎(jade)

      安装 npm install jade --global 
      
      app.js
          const express = require('express');
          const app = express();
      
          const PORT = 8000;
      
          app.all("*",function(req,res,next){
              // 所有路由
              res.header("Access-Control-Allow-Origin","*");
              res.header("Access-Control-Allow-Headers","content-type");
              res.header("Access-Control-Allow-Methods","DELETE,PUT,POST,GET,OPTIONS");
              if (req.method.toLowerCase() == 'options') res.send(200);  
              else next();
          });
      
          app.set('view engine','jade'); 
          app.set('views',__dirname);
      
          app.get('/', function(req, res) {
              res.render('test');
          });
      
          app.listen(PORT, function(err){
              if(!err) {
                  console.log('Server is running at port', PORT);
              }else{
                  console.log(JSON.stringify(err));
              }
          })
      
      test.jade
          doctype html
          html
          title hello,jade
          body
          h1 Hello World
          a(href='https://www.baidu.com') baidu
          input(type='text')
      
          - var a = 1
          case a
              when 0: p 0
              when 1: p 1
              default: p #{friends}
      
      输入http://localhost:8000/即可看到页面
      
    5. 模板引擎(ejs)

      npm install ejs
      
      app.js
          const express = require('express');
          const app = express();
          var cors = require('cors');
          const PORT = 8000;
          app.use(cors());
      
          app.set('view engine','ejs'); 
          app.set('views',__dirname);
      
          app.get('/', function(req, res) {
              res.render('test', {
                  title: 'ejs测试成功',
                  arr: ["a", "b", "c"]
              });
          });
      
          app.listen(PORT, function(err){
              if(!err) {
                  console.log('Server is running at port', PORT);
              }else{
                  console.log(JSON.stringify(err));
              }
          })
      
      test.ejs
          <!DOCTYPE html>
          <html lang="en">
              <head>
                  <meta charset="UTF-8">
                  <meta name="viewport" content="width=device-width, initial-scale=1.0">
                  <meta http-equiv="X-UA-Compatible" content="ie=edge">
                  <title>Document</title>
              </head>
              <body>
                  <h1><%= title %></h1>
      
                  <ul>
                  <% for(var i=0; i<arr.length; i++) { %>
                      <li>
                          <%= arr[i] %>
                      </li>
                  <% } %>
                  </ul>
              </body>
          </html>
      
    6. 处理json数据

      const express = require('express');
      const app = express();
      var cors = require('cors');
      const PORT = 8000;
      app.use(cors());
      
      app.get('/', function(req, res){
          var info={
              'a': 'aaaa',
              'b': 1111
          }
          
          // 方式一 res.json(info);
          // 方式二 res.send(JSON.stringify(info))
          // 方式三 res.status(200).json(info);
      
      })
      
      app.listen(PORT, function() {
          console.log('Node.js listening on port ' + PORT)
      })
      
    7. 请求静态文件

      新建一个public文件夹,在里面放置你的静态文件,比如index.html
      只需要一句代码就搞定一切了 app.use(express.static('public'));
      直接访问http://localhost:8000/index.html即可
      
      你可以添加一个前缀比如 app.use('/static', express.static('public'));
      直接访问 http://localhost:8000/static/index.html
      
    8. 错误处理

      使用pug模板引擎
      创建一个views文件夹,在里面创建一个error.pug文件,输入如下内容
      html
          body
              h1= message
              h2= error.status
              p= error.stack
      
      测试代码
          app.set('view engine','pug'); 
          app.set('views',path.resolve(__dirname, 'views'));
      
          // 制造一个404错误,并将err抛出
          app.use(function(req, res, next) {
              var err = new Error('Not Found');
              err.status = 404;
              //pass error to the next matching route.
              next(err);
          });
          // 接收错误,渲染错误页面
          app.use(function(err, req, res, next) {
              res.status(err.status || 500);
              res.render('error', {
                  message: err.message,
                  error: err
              });
          });
      
    9. 从request中获取信息

      最原始的方法获取request属性
          请求路径 /test/11?a=1
          app.get('/test/:id', function(req, res){
              console.log(req.originalUrl); // /test/1?a=1
              console.log(req.params.id); // 11
              console.log(req.query.a); // 1
              res.send(req.get('Content-Type'));
          })
      
      使用body-parser中间件处理,可以方便地处理请求体的参数
          var bodyParser = require('body-parser');
          app.use(bodyParser.json());
          app.use(bodyParser.urlencoded({ extended: true }));
          app.post('/test', function(req, res, next) {
              console.log(req.body);
          })
      
      同样何以使用cookie-parser,可以方便地处理cookie对象
          npm install cookie-parser
          var cookieParser = require('cookie-parser')
          app.use(cookieParser());
          app.use(express.static('public'));
          app.get('/setcookie', function(req, res) {
              res.cookie('name', 'yjw', {
                  maxAge: 100000, // 过期时间
                  httpOnly: true
              });
              return res.send('cookie设置成功');
          });
          app.get('/getcookie', function(req, res) {
              var name = req.cookies['name'];
              if(name) {
                  return res.send(name);
              }
              return res.send("cookie中无数据")
          });
      
    10. 请求之前和完成之后的回调

      在api最前面添加
      app.use(function (req, res, next) {
          function afterResponse() {
              res.removeListener('finish', afterResponse);
              res.removeListener('close', afterResponse);
              // 这里输入请求完成要执行的代码
              console.log("请求完毕");
          }
          res.on('finish', afterResponse);
          res.on('close', afterResponse);
          // 这里输入请求之前要执行的代码
          console.log("准备请求");
          next();
      });
      
    11. 自定义中间件

      只需要使用app.use传递一个函数即可
      
      app.use(function(req, res, next){
          req.data="testdata";
          next();
      })
      
    12. Django风格的路由

      实际上就是命名一个路由,然后实现跳转
      npm install express-reverse
      
      require('express-reverse')(app);
      app.get('test','/getdata/:data', function(req, res) {
          return res.send(req.params.data);
      })
      
      app.get('/test-redirect', function(req, res, next) {
          res.redirectToRoute('test', { data: 'world' });
      });
      
      然后请求test-redirect即可
      

    文件I/O

    1. 异步读取文件

      const fs = require('fs');
      const path = require('path');
      app.get('/test', function(req, res) {
          fs.readFile(path.resolve(__dirname, 'test.txt'), {encoding: 'utf-8'}, (err, content) => {
              if(err) return console.error(err);
              res.send(content);
          })
      })
      
    2. 文件目录

      app.get('/test', function(req, res) {
          fs.readdir(__dirname, (err, files) => {
              if(err) return console.error(err);
              res.send(files.join(' '));
          })
      })
      
    3. 使用流复制文件

      // highWaterMark是设置缓冲区
      var readable = fs.createReadStream(path.resolve(__dirname, 'test.txt'), { encoding: 'utf8', highWaterMark: 16 * 1024 });
      var writable = fs.createWriteStream(path.resolve(__dirname, 'testbak.txt'));
      readable.pipe(writable);
      
    4. 检查文件是否有权限

      fs.constants.F_OK 读/写/可执行权限
      fs.constants.R_OK 读权限
      fs.constants.W_OK 写权限
      fs.constants.X_OK 可执行权限
      
      var filepath = path.resolve(__dirname, 'test.txt');
      fs.access(filepath, fs.constants.R_OK | fs.constants.W_OK, (err) => {
          if(err) {
              console.log("%s 文件不存在", filepath);
          }else {
              console.log("可以读或者写 %s 此文件", filepath);
          }
      })
      
    5. 检查文件和目录是否存在

      var filepath = path.resolve(__dirname, 'test.txt');
      fs.stat(filepath, function(err) {
          if(!err) {
              console.log('文件或者文件夹存在');
          }else if(err.code === 'ENOENT') {
              console.log('文件或者文件夹不存在')
          }
      })
      
    6. 按行读取

      const readline = require('readline');
      var filepath = path.resolve(__dirname, 'test.txt');
      var linesCount = 0;
      var rl = readline.createInterface({
          input: fs.createReadStream(filepath),
          output: process.stdout,
          terminal: false
      });
      
      rl.on('line', function (line) {
          console.log(line);
          linesCount++;
      });
      rl.on('close', function () {
          console.log(linesCount); 
      });
      
    7. 获取用户输入信息

      const readline = require('readline');
      const rl = readline.createInterface({
          input: process.stdin,
          output: process.stdout
      });
      rl.question('What is your name?', (name) => {
          console.log(`Hello ${name}!`);
          rl.close();
      });
      
    8. 创建文件夹

      fs.mkdir(path.resolve(__dirname, 'test'), (err) => {
          if(err && err.code !== 'EEXIST' ? err : null){
              return console.error(err);
          }else {
              // 此处文件夹已经创建成功,可以对刚创建的文件夹做操作
              
          }
      })
      
    9. 往文件中写数据

      // 直接覆盖
      fs.writeFile(path.resolve(__dirname, 'test.txt'), '我是写入的数据', function(err){
          if(err) return console.error(err);
      });
      
    10. 文件内容替换

      // 将文件中部分文字替换成其他的文字,其中正则flags的gim分别表示全局、不区分大小写、多行匹配
      var filepath = path.resolve(__dirname, 'test.txt');
      fs.readFile(filepath, 'utf-8', function(err, data) {
          if (err) throw err;
          var newValue = data.replace(/11111111/gim, 'a');
          fs.writeFile(filepath, newValue, 'utf-8', function(err, data) {
              if (err) throw err;
              console.log('搞定!');
          })
      })
      
    11. 删除文件

      fs.unlink(path.resolve(__dirname, 'test.txt'),function(err){
          if(err) console.error(err);
          console.log("已删");
      })
      
    12. 使用流读取文件

      let fileBuffer, chunks = [], stream = fs.createReadStream(path.resolve(__dirname, 'test.txt'));
      stream.once('error', (err) => {
          // 出错了就执行此方法
          console.error(err);
      })
      stream.on('data', (chunk) => {
          // 将数据一点点读入到chunks中
          chunks.push(chunk); 
      });
      stream.once('end', ()=>{
          // 读取结束后,调用此方法
          fileBuffer = Buffer.concat(chunks);
          console.log(fileBuffer.toString());
      })
      

    nodejs模块

    ```txt
    node自带的模块处理功能
        module.exports={ // 只能导出一个对象
            a: 'a',
            b: 'b'
        } 
        等价写法如下
        exports.a='a';
        exports.a='b';
        
        导入模块
        const test = require('./test.js');
    
    es6的模块处理
    
    ```
    

    node集群

    app.js
        const cluster = require('cluster');
        const numCPUs = require('os').cpus().length;
    
        if (cluster.isMaster) {
            // 根据电脑cpu的核心数创建多个Worker分支
            for (let i = 0; i < numCPUs; i++) {
                cluster.fork();
            }
            cluster.on('exit', (worker, code, signal) => {
                if (signal) {
                    console.log(`worker was killed by signal: ${signal}`);
                } else if (code !== 0) {
                    console.log(`worker exited with error code: ${code}`);
                } else {
                    console.log(`worker success ${worker.process.pid} died`);
                }
            });
        } else {
            // 让workers共享一个端口
            require('./server.js')();
        }
    
    server.js
        // const http = require('http');
        const express = require('express');
        const app = express();
        var cors = require('cors');
        app.use(cors());
        app.use(express.static('public'));
    
        function startServer() {
            app.get("/test", function(req, res, next){
                res.send('test');
            })
            
            app.listen(8000, function() {
                console.log('Server listening on http://localhost:' + 8000);
            });
        }
        if (!module.parent) { // 判断此文件是否被其他文件引用
            // 这个文件是直接运行的,就直接启动server
            startServer();
        } else {
            // 这个文件是通过其他文件导入执行的,就导出server
            module.exports = startServer;
        }
    

    事件发射器

    const EventEmitter = require('events').EventEmitter;
    
    class Test extends EventEmitter {};
    let t = new Test();
    t.on('fn', (data) => { // 如果你需要设置一次性的监听器用once
        console.log(data);
    })
    
    console.log(t.eventNames()); // 查看所有的订阅者(函数)
    console.log(t.listenerCount("fn")); // 获取指定监听器的数量
    
    t.emit('fn', "abc"); 
    

    自动重载

    自动刷新代码
    npm install -g nodemon
    nodemon app.js
    

    环境变量

    系统环境变量
        console.log(process.env)
    命令行参数
        console.log(process.argv)
    从属性文件中获取配置参数
        npm install properties-reader
        
        app.js
            const path = require('path');
            var PropertiesReader = require('properties-reader');
            var properties = null;
            process.argv.forEach(function (val, index, array) {
                var arg = val.split("=");
                if (arg.length > 0) {
                    if (arg[0] === 'env') {
                        properties = PropertiesReader(path.resolve(__dirname, arg[1] + '.ini'));
                    }
                }
            });
            var someVal = properties.get('yjw.data.a');
            console.log(someVal)
        dev.ini
            [yjw]
            data.a = 1
        运行 node app.js env=dev
    

    Promise的简单使用

    var fn = function(flag) {
        return new Promise(function(resolve, reject) {
            if(flag) {
                resolve("it is true");
            }else {
                reject(new Error("it is false"));
            }
        })
    }
    
    fn(false).then(function(data){
        console.log(data);
    }).catch(function(err){
        console.log(err);
    })
    

    node异常重启

    node是单线程的程序,如果node进程出问题了,那么我们开发的程序自然就崩盘了
    这个时候可以安装一个监视进程,如果node进程挂了,就再次启动
    
    有n种监视进程,这里就列举一个
        forever
            npm install forever -g
    
            process.on('uncaughtException', function (err) {
                console.log(err);
                
                process.exit(1); // 捕获node进程异常之后,结束此进程,目的是利用forever重启node,避免数据库不重连
            });
            forever start index.js // 启动程序
            forever list // 产看forever监视进程
            forever stop 0 // 停止监视进程
    

    NODE_ENV环境变量

    在程序中可以使用process.env.NODE_ENV来辨别当前环境是生产环境还是开发环境
        if(process.env.NODE_ENV === 'production') {
        } else {
        }
    
    设置NODE_ENV的几种方式
        方式一:直接设置
            set NODE_ENV=development&&node app.js
        方式二:.env文件
            npm install env-cmd -g
            编写.env文件,输入NODE_ENV=development
            运行env-cmd .env node app.js即可
        方式三:cross-env插件
            npm install cross-env -g
            cross-env NODE_ENV=development node app.js
    

    异步平行流

    多个任务一起执行
    var async = require('async');
    
    function fn1(callback) {
        setTimeout(function(){
            callback(null, 'a') // 第一个参数是错误值,后面的参数都是成功值
        }, 100)
    }
    
    function fn2(callback) {
        setTimeout(function(){
            callback(null, 'b')
        }, 200)
    }
    
    function fn3(callback) {
        setTimeout(function(){
            callback(null, 'c')
        }, 300)
    }
    
    async.parallel([ fn1, fn2, fn3 ], function(err, results) {
        if (err) {
            return console.error(err);
        }
        console.log(results); // [ 'a', 'b', 'c' ]
    });
    

    同步平行流

    多个任务一个接一个执行
    function fn1(callback) {
        setTimeout(function(){
            callback(null, 'a') 
        }, 100)
    }
    
    function fn2(callback) {
        setTimeout(function(){
            callback(null, 'b')
        }, 200)
    }
    
    function fn3(callback) {
        setTimeout(function(){
            callback(null, 'c')
        }, 300)
    }
    
    async.series([ fn1, fn2, fn3 ], function(err, results) {
        if (err) {
            return console.error(err);
        }
        console.log(results); // [ 'a', 'b', 'c' ]
    });
    

    同步值传递平行流

    多个任务一个接一个执行,并且上一个任务的返回值传递给下一个任务
    
    function fn1(callback) {
        setTimeout(function(){
            callback(null, 'a') 
        }, 100)
    }
    
    function fn2(data, callback) {
        setTimeout(function(){
            callback(null, data+'b')
        }, 200)
    }
    
    function fn3(data, callback) {
        setTimeout(function(){
            callback(null, data+'c')
        }, 300)
    }
    
    async.waterfall([ fn1, fn2, fn3 ], function(err, results) {
        if (err) {
            return console.error(err);
        }
        console.log(results); // abc
    });
    

    异步遍历

    async.each
        async.each(['a', 'b', 'c'], function(item, callback){
            console.log(item);
            callback(null);
        }, function(err){
            console.log(err);
        })
    async.times
        长for循环,必须使用这个,要不然你的node程序就卡机了
        async.times(5, function(n, next) {
            next(null, n);
        }, function(err, results) {
            console.log(err);
            console.log(results); // [ 0, 1, 2, 3, 4 ]
        });
    

    使用socket.io实现一个钟表功能

    npm install socket.io
    
    服务端代码
        const express = require('express');
        const app = express();
        var cors = require('cors');
        app.use(cors());
    
        const server = app.listen(8000, console.log("Socket.io Hello World server started!"));
        const io = require('socket.io')(server);
        io.on('connection', (socket) => {
            console.log("Client connected!");
            socket.on('receivefromclient', (msg) => {
                console.log(msg);
            })
            setInterval(function(){
                var today=new Date()
                var h=today.getHours()
                var m=today.getMinutes()
                var s=today.getSeconds()
                socket.emit('receivefromserver', h+":"+m+":"+s);
            }, 1000)
        });
    前端代码    
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <meta http-equiv="X-UA-Compatible" content="ie=edge">
            <title>Document</title>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
        </head>
        <body>
            <p id="message"></p>
        </body>
    
        <script>
            var socket = io("http://localhost:8000");
            setInterval(function(){
                socket.on("receivefromserver", function(msg) {
                    document.getElementById('message').innerHTML = msg;
                });
            }, 1000)
            socket.emit('receivefromclient', '收到消息!');
        </script>
    
        </html>
    
  • 相关阅读:
    亚信防毒墙网络版卸载
    Ubuntu之apt
    Python(00):内存中读写数据StringIO和BytesIO
    Windows使用cmd命令行中查看、修改、删除与添加环境变量
    微信小程序教程
    微信小程序之云开发
    微信小程序-简易计算器
    第一个微信小程序——实现获取用户信息替换用户名和头像到首页
    Python(00):RSA加解密
    Python(00):使用selenium模块
  • 原文地址:https://www.cnblogs.com/ye-hcj/p/10272565.html
Copyright © 2020-2023  润新知