zoukankan      html  css  js  c++  java
  • Nodejs笔记(二)

    Nodejs事件

      Node.js 所有的异步I/O 操作在完成时都会发送一个事件到事件队列。

      Node.js里面的许多对象都会分发事件:一个net.Server对象会在每次有新连接时分发一个事件, 一个fs.readStream对象会在文件被打开的时候发出一个事件。 所有这些产生事件的对象都是 events.EventEmitter 的实例。可以通过require("events")来访问该模块。

     EventEmitter 的用法:

    //event.js 
    var EventEmitter = require('events').EventEmitter; 
    var event = new EventEmitter(); 
    event.on('some_event', function() { 
        console.log('some_event occured.'); 
    }); 
    setTimeout(function() { 
        event.emit('some_event'); 
    }, 1000); 

      运行代码,1秒后控制台输出了 'some_event occured'。原理是 event 对象 注册了事件 some_event 的一个监听器,然后通过 setTimeout 在1000毫秒以后向 event 对象发送事件 some_event,此时会调用some_event 的监听器。

    EventsEmitter

       events 模块只提供了一个对象: events.EventEmitter。EventEmitter 的核心就是事件触发与事件监听器功能的封装。

       EventEmitter 的每个事件由一个事件名和N个参数组成,对于每个事件,EventEmitter 支持若干个事件监听器。当事件触发时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递。回调函数是按照顺序依次被调用的。

    var events = require('events'); 
    var emitter = new events.EventEmitter(); 
    emitter.on('someEvent', function(arg1, arg2) { 
        console.log('listener1', arg1, arg2); 
    }); 
    emitter.on('someEvent', function(arg1, arg2) { 
        console.log('listener2', arg1, arg2); 
    }); 
    emitter.emit('someEvent', 'void', 2008); 

    结果是

    listener1 void 2008
    listener2 void 2008

      EventEmitter.on(event, listener)、emitter.addListener(event, listener) 为指定事件注册一个监听器,接受一个字符串event 和一个回调函数listener。

    server.on('connection', function (stream) {
      console.log('someone connected!');
    });

      EventEmitter.emit(event, [arg1], [arg2], [...]) 触发event 事件,传递若干可选参数到事件监听器的参数表。

      EventEmitter.once(event, listener) 为指定事件注册一个单次监听器,即监听器最多只会触发一次,触发后立刻解除该监听器。

    server.once('connection', function (stream) {
      console.log('We have our first user!');
    });

      EventEmitter.removeListener(event, listener) 移除指定事件的某个监听器,listener 必须是该事件已经注册过的监听器。

    var callback = function(stream) {
      console.log('someone connected!');
    };
    server.on('connection', callback);
    // ...
    server.removeListener('connection', callback);


     

    Nodejs路由

      有时要为路由提供请求的URL和其他需要的GET及POST参数,随后路由需要根据这些数据来执行相应的代码。

      因此,需要查看HTTP请求,从中提取出请求的URL以及GET/POST参数。这一功能应当属于路由还是服务器(甚至作为一个模块自身的功能)确实值得探讨,但这里暂定其为我们的HTTP服务器的功能。

      所需要的所有数据都会包含在request对象中,该对象作为onRequest()回调函数的第一个参数传递。但是为了解析这些数据,我们需要额外的Node.JS模块,它们分别是url和querystring模块。也可以用querystring来解析POST的数据。

    var http = require("http");
    var url = require("url");
    
    function start() {
      function onRequest(request, response) {
        var pathname = url.parse(request.url).pathname;
        console.log("Request for " + pathname + " received.");
        response.writeHead(200, {"Content-Type": "text/plain"});
        response.write("Hello World");
        response.end();
      }
    
      http.createServer(onRequest).listen(8888);
      console.log("Server has started.");
    }
    
    exports.start = start;

      这个应用现在可以通过请求的URL路径来区别不同请求了--这使我们得以使用路由(还未完成)来将请求以URL路径为基准映射到处理程序上。

      在所要构建的应用中,这意味着来自/start和/upload的请求可以使用不同的代码来处理。

      建立一个名为router.js的文件,添加以下内容:

    function route(pathname) {
      console.log("About to route a request for " + pathname);
    }
    
    exports.route = route;

      服务器应当知道路由的存在并加以有效利用。当然可以通过硬编码的方式将这一依赖项绑定到服务器上,但是这会是一件痛苦的事,可以使用依赖注入的方式较松散地添加路由模块。

      首先,可以扩展一下服务器的start()函数,以便将路由函数作为参数传递过去:

    var http = require("http");
    var url = require("url");
    
    function start(route) {
      function onRequest(request, response) {
        var pathname = url.parse(request.url).pathname;
        console.log("Request for " + pathname + " received.");
    
        route(pathname);
    
        response.writeHead(200, {"Content-Type": "text/plain"});
        response.write("Hello World");
        response.end();
      }
    
      http.createServer(onRequest).listen(8888);
      console.log("Server has started.");
    }
    
    exports.start = start;

      同时,需要扩展index.js,使得路由函数可以被注入到服务器中:

    var server = require("./server");
    var router = require("./router");
    server.start(router.route);

      如果现在启动应用(node index.js),随后请求一个URL,将会看到应用输出相应的信息,这表明我们的HTTP服务器已经在使用路由模块了,并会将请求的路径传递给路由:

    bash$ node index.js
    Request for /foo received.
    About to route a request for /foo

    Nodejs GET/POST请求

      在很多场景中,服务器都需要跟浏览器打交道,如表单提交,Ajax请求等。表单提交到服务器一般都使用GET/POST请求。

      获取GET请求的内容:

      由于GET请求直接被嵌入在路径中,URL是完整的请求路径,包括了?后面的部分,因此可以手动解析后面的内容作为GET请求的参数。node.js中url模块中的parse函数提供了这个功能。

    var http = require('http');
    var url = require('url');
    var util = require('util');
    
    http.createServer(function(req, res){
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end(util.inspect(url.parse(req.url, true)));
    }).listen(3000);

      在浏览器中访问http://localhost:3000/user?name=Mary&email=Mary@163.com 然后查看返回结果:

    {
      protocol:null,
      slashes:null,
      auth:null,
      host:null,
      port:null,
      hostname:null,
      hash:null,
      search:"?name=Mary&email=Mary@163.com",
      query:{name:"Mary",email:"Mary@163.com"},
      pathname:"/user",
      path:"/user?name=Mary&email=Mary@163.com",
      search:"/user?name=Mary&email=Mary@163.com"
    }

      获取POST内容

      POST请求的内容全部的都在请求体中,http.ServerRequest并没有一个属性内容为请求体,原因是等待请求体传输可能是一件耗时的工作。

    比如上传文件,而很多时候可能并不需要理会请求体的内容,恶意的POST请求会大大消耗服务器的资源,所有node.js默认是不会解析请求体的,当需要的时候,需要手动来做。

    var http = require('http');
    var querystring = require('querystring');
    var util = require('util');
    
    http.createServer(function(req, res){
        var post = '';     //定义了一个post变量,用于暂存请求体的信息
    
        req.on('data', function(chunk){    //通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中
            post += chunk;
        });
    
        req.on('end', function(){    //在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。
            post = querystring.parse(post);
            res.end(util.inspect(post));
        });
    }).listen(3000);
  • 相关阅读:
    Mybatis 使用Mybatis时实体类属性名和表中的字段名不一致
    getResourceAsStream 地址
    Memory Allocation with COBOL
    静态call 动态call LINK
    反编译
    eclipse 设置英文
    WAR/EAR 概念
    application.xml
    对ContentProvider中getType方法的一点理解
    总结使人进步,可视化界面GUI应用开发总结:Android、iOS、Web、Swing、Windows开发等
  • 原文地址:https://www.cnblogs.com/linda586586/p/4167879.html
Copyright © 2011-2022 走看看