一、Node.js 究竟是什么?

Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念。它的目标是帮助程序员构建高度可伸缩的应用程序,编写能够处理数万条同时连接到一个(只有一个)物理机的连接代码。

Node 本身运行 V8 JavaScript。等等,服务器上的 JavaScript?对,您没有看错,就是Javascript。对于只在客户机上使用 JavaScript 的程序员而言,服务器端 JavaScript 可能是一个新概念,但这个概念本身并非遥不可及,因此为何不能在服务器上使用客户机上使用的编程语言?

什么是 V8V8 JavaScript 引擎是 Google 用于其 Chrome 浏览器的底层 JavaScript 引擎。实际上,JavaScript 引擎负责解释并执行代码。Google 使用 V8 创建了一个用 C++ 编写的超快解释器,该解释器拥有另一个独特特征;您可以下载该引擎并将其嵌入任何 应用程序。V8 JavaScript 引擎并不仅限于在一个浏览器中运行。因此,Node 实际上会使用 Google 编写的 V8 JavaScript 引擎,并将其重建为可在服务器上使用。

(一)回调函数

你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。

回调函数,就是由你自己写的。系统在必要的时候,就会调用你写的回调函数,这样你就可以在回调函数里完成你要做的事。比如网页中点击事件里所执行的函数,当用户点击浏览器就会执行我们写的这个函数。而这个函数就是回调函数。

(二)事件驱动

创建了服务器,并且向创建它的方法传递了一个函数。无论何时我们的服务器收到一个请求,这个函数就会被调用。我们不知道这件事情什么时候会发生,但是我们现在有了一个处理请求的地方:它就是我们传递过去的那个函数。至于它是被预先定义的函数还是匿名函数,就无关紧要了。这个就是传说中的 回调 。我们给某个方法传递了一个函数,这个方法在有相应事件发生时调用这个函数来进行 回调

让我们再来琢磨琢磨这个新概念。我们怎么证明,在创建完服务器之后,即使没有 HTTP 请求进来、

我们的回调函数也没有被调用的情况下,我们的代码还继续有效呢?我们试试这个:

var http = require("http");

var myServer=http.createServer(function(request, response) {

console.log(Request received);

});

myServer.listen(8888);

console.log("Server has started.");

 

注意:在我们的回调函数触发的地方,我用 console.log 输出了一段文本。在 HTTP

服务器开始工作 之后 ,也输出一段文本。

当我们与往常一样,运行它 node server.js 时,它会马上在命令行上输出“ Server has started. ” 。当我

们向服务器发出请求(在浏览器访问 http://localhost:8888/ ) , “ Request received. ”这条消息就会在

命令行中出现。

这就是事件驱动的异步服务器端 JavaScript 和它的回调啦!

(请注意,当我们在服务器访问网页时,我们的服务器可能会输出两次Request received. ” 。那是

因为大部分服务器都会在你访问 http://localhost:8888 / 时尝试读取 http://localhost:8888/favicon.ico )

(三)阻塞非阻塞

同步/异步:   消息通知机制相关=>需要自己关注还是提供callback

阻塞/非阻塞:等待消息时的状态=>是否可以干别的事情

同步阻塞: 劫匪看着衰男把钱装好,不能干其他事情

同步非阻塞:劫匪自己也到处搜索宝贝,但是还要不时跑回来看看钱装好没有。

异步非阻塞:劫匪自己也到处搜索宝贝,衰男把钱装好了自动过来告诉劫匪好了

异步阻塞:  劫匪就在那里傻等着,也不用管钱是否装好,衰男把钱装好了自动过来告诉劫匪好了 

我们需要通过它提过的一些支持的库自己编写,无法像Apache那样直接运行,V8引擎本身使用了一些最新的编译技术。这使得用Javascript这类脚本语言编写出来的代码运行速度获得了极大提升,又节省了开发成本。对性能的苛求是Node的一个关键因素。本质上就是为文件系统、数据库之类的资源提供接口。

阻塞非阻塞:可以简单理解为需要做一件事能不能立即得到返回应答,如果不能立即获得返回,需要等待,那就阻塞了,否则就可以理解为非阻塞。

例如:

我去买一本书,立即买到了,这就是非阻塞;
如果恰好书店没有,我就等一直等到书店有了这本书买到了才走,这就是阻塞;

(四)模块化

正如我们买了一个智能手机那样,我们总是可以安装第三方软件来扩展手机的功能,听音乐,玩游戏,阅读等等。对于nodejs也是一样一样的。

本身nodejs相当一个平台,您也可以通过安装模块来扩展 Node 的功能。可用于 Node 的模块极大地 增强了这个产品,那些模块非常有用,将使用 Node 的开发人员通常会安装几个模块。因此,模块也就变得越来越重要,甚至成为整个产品的一个关键部分。

(五)函数式编程

简单说,“函数式编程”是一种编程范式(programming paradigm),也就是如何编写程序的方法论。它属于结构化编程的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用。用之前学过的知识来说就是,我们把要完成的一个小功能写成一个函数,用于被调用,这就是函数式编程

 

二、编写第一个node程序

 

(一)示例代码

 

 //1 通过requer导入http模块,并且返回一个对象

 

var http=require("http");

 

// 2 创建服务器,设置回调函数

 

var server=http.createServer(function(){

 

  console.log("服务器运行了");

});

 

// 3 监听端口,

 

server.listen("8888");

 

console.log("监听成功");

(二)运行第一个程序

进入项目工程目录

Node app.js

(三)访问第一个服务器程序

1、localhost:8888

2、127.0.0.1:8888

(四)设置请求响应对象,并且响应给客户端数据

var http=require("http");

var server=http.createServer(function(request,response){

   console.log("服务器运行了");

   response.writeHead(200,{"content-type":"text/html;charset=utf-8"})

   response.write("<h1>hello world</h1>");

   response.end();

});

server.listen("8888");

console.log("监听成功");

三、Node项目工程目录结构

1.app.js  服务器文件

2.Public(文件夹) 静态资源

3.routes (文件夹)   路由

4.views (文件夹)  视图文件

5.dist (文件夹)   上线后的资源

 

五、完整请求响应

//通过require导入http模块,并且返回一个函数
var http=require("http");
var fs=require("fs");
//创建服务器,设置回掉函数
var server=http.createServer(function(request,response){
  console.log("服务区运行了");
  var newPath=request.url.split(".");
  if(newPath[1]=="html"){
    fs.readFile("public"+request.url,"utf-8",function(error,data){
      if(error==null){
        response.writeHead(200,{"content-type":"text/html;charset=utf-8"});
        response.write(data);
        response.end();
      }
    });
  }else if(newPath[1]=="js"){
    fs.readFile("public"+request.url,function(error,data){
      if(error==null){
        response.writeHead(200,{"content-type":"javascript"});
        response.write(data);
        response.end();
      }
    });
  }else if(newPath[1]=="css"){
    fs.readFile("public"+request.url,function(error,data){
      if(error==null){
        response.writeHead(200,{"content-type":"text/css;charset=utf-8"});
        response.write(data);
        response.end();
      }
    });
  }else if(newPath[1]=="png"||"jpg"||"gif"){
    fs.readFile("public"+request.url,function(error,data){
      if(error==null){
        response.writeHead(200,{"content-type":"image/newPath[1];charset=utf-8"});
        response.write(data);
        response.end();
      }
    });
  }
});
//监听端口
server.listen("8888");
console.log("监听成功!");

六、Fs模块 文件解析模块

返回哪个页面,首先要知道用户请求的是什么网页,获得请求路径

    两个方法获取请求路径,请求文件:

    1.对象自带属性—URL属性:request.url

    2.url模块:var mypath=require(url)

■引入fs

   var myfs=require(fs)

■通过fs读取

   参数:

    1.路径,2.字符串编码集,3.回调函数,读取完毕后调用的函数:成功or失败

    myfs.readFile(“路径"+mypath,"utf-8",function(err,data){

       response.writeHead(200,{"content-type":"text/html"});

       response.write(data);        

       response.end();

   });

 var fs =require(fs);//加载文件系统模块

 fs.readFile(“路径"+mypath,utf-8",function(err,data){

       response.writeHead(200,{"content- type":"text/html"});

        console.log(err);

        response.write(data);        

       response.end();

   });

七、路由

(一)Routes目录下新建sendFile.js路由文件

ar fs=require("fs");

exports.sendHtml=function(request,response){

      fs.readFile("public"+request.url,"utf-8",function(error,data){

           // console.log(data)

           if(error==null){

                response.writeHead(200,{"content-type":"text/html;charset=utf-8"});

                response.write(data);

                response.end();

           }

       })

  }

exports.sendCss=function(request,response){

      fs.readFile("public"+request.url,"utf-8",function(error,data){

          // console.log(data)

          if(error==null){

                response.writeHead(200,{"content-type":"text/css;charset=utf-8"});

                response.write(data);

                response.end();

          }

     })

 }

exports.sendImg=function(request,response){

    fs.readFile("public"+request.url,function(error,data){

        var newPath=request.url.split(".");

        // console.log(data)

        if(error==null){

            response.writeHead(200,{"content-type":"image/"+newPath[1]});

            response.write(data);

            response.end();

        }

    })

exports.sendjs=function(request,response){

    fs.readFile("public"+request.url,function(error,data){

        var newPath=request.url.split(".");

        // console.log(data)

        if(error==null){

            response.writeHead(200,{"content-type":"javascript"});

            response.write(data);

            response.end();

        }

    })

}

(二)App.js中导入sendFile.js模块

 

// 1 通过requer导入http模块,并且返回一个对象

 

var http=require("http");

 

// 2 创建服务器,设置回调函数

 

// 引入读文件的模块 fs

 

var fs=require("fs");

 

var sendFile=require("./routes/sendFile");

 

var server=http.createServer(function(request,response){

 

    console.log("服务器运行了");

 

    var newPath=request.url.split(".");

 

    if(newPath[1]=="html"){

 

        sendFile.sendHtml(request,response);

 

    }else if(newPath[1]=="css"){

 

        sendFile.sendCss(request,response)

 

    }else if(newPath[1]=="jpg"||newPath[1]=="gif"||newPath[1]=="png"){

 

        sendFile.sendImg(request,response)

 

    }else if(newPath[1]=='js'){

   sendFile.sendjs(request,response);

}

 

    console.log(newPath)

 

})

 

// 3 监听端口,

 

server.listen("8888");

 

console.log("监听成功");

 

 

 

posted on 2017-09-26 16:02  hongyeye  阅读(186)  评论(0编辑  收藏  举报