Nodejs入门实践第一讲Nodejs基础

Nodejs是javascript的运行程序,使用Nodejs最大的优点是可以让javascript运行在服务器端,NodeJS是基于chrome的v8架构的,它主要的的特点是基于异步的I/O处理,所有的事件都会被事件循环器处理,当事件完成通过回调函数来传递结果,这和典型的Ajax请求一样。这样直接导致Node的程序都是单线程的,单线程的优点是程序设计简单,不用考虑复杂的线程通信,这样也就没有所谓的死锁问题,虽然Node是单线程,但由于其异步执行的优势,使得Node也可以轻松的实现并发。

NodeJS的安装

直接通过 https://nodejs.org/en/ 网站即可下载Nodejs,当前的最新版本9.3.0,建议使用8.9.3稳定版,下载NodeJS的时候依然建议下载非安装版,选择other download。

NodeJS的下载路径

之后选择Binary (.zip)这个进行下载

NodeJS的下载路径

下载完成之后,解压,把Nodejs的安装目录添加到环境变量的path中,安装就完成了(注意Nodejs中没有bin路径)。

NPM简介

要很好的使用npm,在目前的NodeJS中,npm是自动安装的,大家可以发现NodeJS目录中有npm.cmd程序,这是一个可执行文件,它用来运行npm,npm是一个模块管理工具,有点类似于maven,开发人员可以将模块下载到项目中或者一个全局的位置,全局的位置默认会在NodeJS安装目录的node_modules 文件夹中。这里仅仅只介绍几个简单的命令,如果希望详细研究NPM,可以查询npm的官方文档。

通过命令npm -v 可以查询npm的版本

>npm -v
5.5.1

使用npm install可以安装模块,有一个非常好用的前台模块管理工具bower,我们安装一下bower,通过如下命令可以安装

D:\test (master -> origin)
> npm install bower -g
npm WARN deprecated bower@1.8.2: ...psst! Your project can stop working at any moment because its dependencies can change. Prevent this by migrating to Yarn: https://bower.io/blog/2017/how-to-migrate-away-from-bower/
D:\nodejs\bower -> D:\nodejs\node_modules\bower\bin\bower
+ bower@1.8.2
added 1 package in 30.176s

加上-g表示全局安装,安装完成之后会存储到nodejs目录的node_modules文件夹中。如果不使用全局安装会自动安装在本地目录中。另外可以通过@来指定安装的版本号

>npm install jquery@latest -g
+ jquery@3.2.1
added 1 package in 2.313s

已上安装了jquery的最新版。另外通过remove可以移除module

> npm remove bower -g
removed 1 package in 3.282s

npm就简单介绍到这里,接下来开始我们的第一个nodejs的程序

nodejs起步

nodejs是一个javascript的运行环境,要运行第一个helloworld的程序,首先建立一个js的文件,我建立了begin.js在该文件中写了一行代码

console.log("hello world!");

之后在该文件夹中使用node命令来执行这个文件

E:\study\nodejs_2018\01_hellojs>node begin.js
hello world!

输出了结果,这也就表示Nodejs已经成功完成安装。

require介绍

在Nodejs中提供了require函数来加载另外一个模块,这个模块可以是通过npm下载的也可以是自定义模块,首先我们自己定义一个函数模块,创建method.js文件

exports.M = {
    begin: function() {
        console.log("begin js");
    },
    end: function () {
        console.log("end js");
    }
}

已上代码通过exports生成了一个M模块,里面有begin和end两个方法。下面在一个module1.js文件中引入该模块

var m = require("./methods")
console.log(m);
m.M.begin();
m.M.end();

通过require引入了该模块,注意要加上./ ,另外就是methods不加js,并且定义了变量m来存储该模块,此后即可通过m.M来引入模块中的方法。

查询一下结果

E:\study\nodejs_2018\01_hellojs>node module1.js
{ method: { begin: [Function: begin], end: [Function: end] } }##显示模块中的值
begin js ##调用模块的begin方法
end js

创建一个nodejs的server

Nodejs由于是javascript的运行环境,所以我们可以直接将javascript运行在服务器端,接下来我们编写一个server.js来启动一个简单的服务。首先创建server.js文件,完成如下几个步骤

1、引入http模块

var http = require("http")

2、创建server

http.createServer(serverOk).listen(8088);

已上代码创建了一个server,当server创建完成之后会执行回调函数serverOk,该回调函数中有两个参数一个是request,另外一个是response。该server启动在8088端口中。

3、编写回调函数

function serverOk(req,resp) {
   resp.writeHead(200,{"Content-type":"text/plain"});
   resp.write("hello nodejs!");
   resp.end();
};

回调函数有两个参数,req等于request对象,resp等于response对象,首先使用resp.writeHead()编写简单的输出信息,状态为200,类型是原始类型,并且输出了hello nodejs,最后通过resp.end()结束输出。

4、运行

首先看看完整代码

var http = require("http");
function serverOk(req,resp) {
   resp.writeHead(200,{"Content-type":"text/plain"});
   resp.write("hello nodejs!");
   resp.end();
};
http.createServer(serverOk).listen(8088);

使用node运行之后,只要在浏览器输入localhost:8088,会看到"hello nodejs!"的字符输出。

基于模块来修改上一个程序

我们可以将创建服务器的这段代码编写到一个模块中,首先创建server_module.js

var http = require("http");

function serverOk(req,resp) {
    resp.writeHead(200,{"Content-type":"text/plain"});
    resp.write("hello node module!");
    resp.end();
}
module.exports = {
    startServer: function(port) {
        http.createServer(serverOk).listen(port);
    }
};

这里变换了一种写法,首先在exports前增加了module,个人感觉这样说明要清晰一些,当然module是可以省略的,另外就是该module并没有编写具体的导出的名称,此时可以直接调用,该module中有两个方法,startServer表示启动服务,此时回调serverOk写在了模块的外面,这表示serverOk是私有的,不会被导出(就当前例子中,该方法也没有导出的意义)。调用代码也比较简单,创建文件test.js

var Server = require("./server_model");
console.log(Server);//输出确定仅仅导出startServer
Server.startServer(8099);

运行之后访问localhost的8099端口即可看到相应的输出。但这个server显然有一个比较严重的问题,就是他只能监听一个请求,另外就是不能渲染html。下面我们先来解决html的渲染问题。然后在解决路由问题

渲染html文件

渲染html是比较重要的一个步骤,Nodejs通过文件的读写来完成该操作,首先需要引入fs这个模块

var fs = require("fs");

接着通过fs.ReadFile可以读取文件

fs.readFile(path,null,function (error,data) {
        if(error) {
            resp.writeHead(404);
            resp.write("find file error!");
        }
        resp.writeHead(200,{"Content-type":"text/html"});
        resp.write(data);
        resp.end();
    });

第一个参数表示file的路径,第二个参数用来存储传入的数据,第三个参数就是回调,回调中有两个参数,第一个表示error,如果发现错误就会为第一个参数赋值,第二个参数表示如果成功返回的内容。代码中首先判断了是否有error,如果没有error就直接输出data,data就是读取到的html的文件内容,注意content-type的类型必须修改为text/html。如果发现错误直接显示404.

完整代码如下所示

var http = require("http");
var fs = require("fs");

function renderHTML(path,resp) {
    fs.readFile(path,null,function (error,data) {
        if(error) {
            resp.writeHead(404);
            resp.write("find file error!");
        } else {
            resp.write(data); 
        }
        resp.end();
    });

}

function serverOk(req,resp) {
    resp.writeHead(200,{"Content-type":"text/plain"});
  //渲染hello.html
    renderHTML("./hello.html",resp);
}
module.exports = {
    startServer: function(port) {
        http.createServer(serverOk).listen(port);
    }
};

调用代码和上一节类似,然后看一下hello.html文件并且完成服务器的启动

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>hello html</h1>
</body>
</html>

此时启动,并且访问localhost的8099即可显示hello.html的内容。

路由

这一小节将要实现不同的请求访问不同的页面,操作原理非常简单,通过request的url可以获取访问路径,通过url模块中的parse方法可以将url转换为json对象,其中pathname可以获取访问的路径变量。将server_module.js的代码稍作调整即可

var http = require("http");
var fs = require("fs");
var url = require("url")

function renderHTML(path,resp) {
    //路径判断
    if(path=="/"||path=="") {
        path = "./index.html";
    } else {
        path = "./"+path+".html";
    }
    //console.log(path);
    fs.readFile(path,null,function (error,data) {
        if(error) {
            resp.writeHead(404);
            resp.write("find file error!");
        } else {
            resp.write(data);
        }
        resp.end();
    });

}

function serverOk(req,resp) {
    resp.writeHead(200,{"Content-type":"text/html"});
    //获得访问的路径,如果输入localhost:8089/abc/bbd会得到/abc/bbd
    var pathname = url.parse(req.url).pathname;
    renderHTML(pathname,resp);
}
module.exports = {
    startServer: function(port) {
        http.createServer(serverOk).listen(port);
    }
};

这里简单实现了Nodejs的基本流程,但在实际开发中一般都不会使用原生的方法来处理,Nodejs中有大量的模块可以帮助开发人员来完成这些操作,接下来将会以Express为例来详细讲解。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • Node.js是目前非常火热的技术,但是它的诞生经历却很奇特。 众所周知,在Netscape设计出JavaScri...
    w_zhuan阅读 3,610评论 2 41
  • Node.js是目前非常火热的技术,但是它的诞生经历却很奇特。 众所周知,在Netscape设计出JavaScri...
    Myselfyan阅读 4,066评论 2 58
  • 九月的最后一天 开学一个月了,然而并没有什么 我总觉得会找到与众不同的事,一些 我也不知道了不起的事 跟这差不多的...
    愤怒的小汪阅读 313评论 0 1
  • 2017年,来北京的第二年。2016年的春节,拖家带口从南方来到北方,从一个几乎只有夏天的城市来到春夏秋冬四季分明...
    知瑜阅读 304评论 1 1
  • 今天是工作的第二天,除了没有适应工作内容外其他的基本适应~感触最深的还是来自同事的热情与温暖:帮我适应环境,热情的...
    有才家的小妞阅读 205评论 0 0