NodeJS异步实现

Node.js异步编程的直接体现就是回调,它依托于回调来实现,但不能说使用了回调他就是异步了

回调函数在完成任务后就会被调用,Node使用了大量的回调函数,Node所有的API都支持回调函数

例如:我们可以一边读取文件一边执行其他命令,在文件读取完成后,我们将文件内容作为回调的参数返回,这样执行代码的时候就不会有阻塞或等待I/O操作

这样就打打提高了Node.js性能,可以处理大量的并发请求。

一、阻塞代码示例

1、创建一个测试文件text.txt文件内容如下:

文件I/O操作:open the file ==>帅哥很帅

创建index.js文件

#!/usr/bin/env node

var fs = require("fs");

var data = fs.readFileSync('test.txt');

console.log(data.toString());
console.log('帅哥执行命令测试~~~');

2、执行结果

LuoTimdeMacBook-Pro-2:bin luotim$ node index.js
文件I/O操作:open the file ==>帅哥很帅
帅哥执行命令测试~~~

从结果上可以看出来先进行了I/O操作才执行的输出命令

二、非阻塞代码的实现

修改代码

#!/usr/bin/env node

var fs = require("fs");

fs.readFile('test.txt',function (error,data) {
    if (error) return console.error(error);
    console.log(data.toString());
});

console.log("异步程序测试~~");

2、执行结果

LuoTimdeMacBook-Pro-2:bin luotim$ node index.js
异步程序测试~~
文件I/O操作:open the file ==>帅哥很帅

从结果上就可以看出第一个程序在文件读取完后才执行完程序,第二个实例我们不需要等待文件读取完这样就可以在读取文件的同时执行后续的代码,大大提高了程序性能。

对于Nodejs来说阻塞是按顺序执行的,而非阻塞不需要按照顺序执行直接把相关的I/O操作交给回调函数执行。

Node.js事件循环

Nodejs是单进程和单线程应用程序,但是通过事件和回调支持并发(看上面异步实现),所以性能非常高。

并且Nodejs的每一个API都是异步的,并作为独立的一个线程运行,使用异步函数调用,并处理并发!

Nodejs基本上所有的事件机制都是使用设计模式中“观察者模式”实现

#观察者模式
观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式)是软件设计模式的一种。
在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。
这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。

Node.js单线程类似进入一个while(true)的事件循环,知道没有事件观察者退出,每个异步事件都生成一个事件观察者,如果没有事件发生就调用该回调函数。

事件驱动程序

Node.js使用事件驱动模型,当web server接收到请求,就把他关闭然后进行处理,然后去服务下一个web请求。

当这个请求完成,它被放回处理队列中,当到达队列开头,这个结构就返回给用户。

因为webserver一直接受请求不等待任何的I/O读写操作(非阻塞I/O或者事件驱动I/O)

整个的驱动流程就是如上图这样实现的,非常简洁.

二、通过events模块来绑定和触发事件

1、导入模块并实例化对象

//引入events模块
var events = require("events");

//创建evenEmitter对象
var evenEmitter = new events.EventEmitter();

2、绑定定事件处理程序,当事件触发后执行的程序

//绑定事件及事件的处理程序
evenEmitter.on('evenName',eventHandler);

3、可以通过程序来触发

//我们可以通过程序触发事件
evenEmitter.emit('evenName');

实例:

#!/usr/bin/env node

//引入events模块
var events = require("events");

//创建evenEmitter对象
var eventEmitter = new events.EventEmitter();

// 创建事件处理程序
var connectHandler = function connected() {
   console.log('连接成功。');

   // 触发 data_received 事件
   eventEmitter.emit('data_received');
};

// 绑定 connection 事件处理程序
eventEmitter.on('connection', connectHandler);

// 使用匿名函数绑定 data_received 事件
eventEmitter.on('data_received', function(){
   console.log('数据接收成功。');
});

// 触发 connection 事件
eventEmitter.emit('connection');

console.log("程序执行完毕。");

梳理流程图:(用于梳理)事件的绑定执行

Node.js之路【第三篇】NodeJS异步实现的更多相关文章

  1. Node.js之路【第一篇】初识Node.js

    什么是Node.js 1.Node.js就是运行在服务端的JavaScrip. 2.Node.js是一个基于Chrome JavaScrip运行时简历的一个平台. 3.Node.js是一个非阻塞I/O ...

  2. Node.js入门教程 第三篇 (模块及路由)

    Node.js的模块 Node.js的模块与传统面向对象的类(class)不完全相同.Node.js认为文件即模块,即一个文件是一个模块.单一文件一般只专注做一件事情,保证了代码的简洁性. 创建模块: ...

  3. Node.js之路【第二篇】Nodejs中的pip(NPM)&REPL

    什么是NPM 在学Python的时候我们肯定会使用第三方模块或者编写模块供别人使用,我们有一个非常好用的pip来帮我们管理我们的模块包!那么Nodejs重的模块包呢? 对没错就是NPM,他是随同Nod ...

  4. 《唐三学node.js系列》—魂士篇&&三哥初始node.js

    前言 如果你有一定的前端基础,比如 HTML.CSS.JavaScript.jQuery.那么Node.js 能让你以最低的成本快速过渡成为一个全栈工程师(我称这个全栈为伪全栈,我认为的全栈也要精通数 ...

  5. Node.js最新技术栈之Promise篇

    前言 大家好,我是桑世龙,github和cnodejs上的i5ting,目前在天津创业,公司目前使用技术主要是nodejs,算所谓的MEAN(mongodb + express + angular + ...

  6. 一名全栈工程师Node.js之路-转

    Node.js 全球现状 虽然 Node.js 在国内没有盛行,但据 StackOverflow 2016 年开发者调查,其中 node.js .全栈.JavaScript 相关的技术在多个领域(包括 ...

  7. Node.js写文件的三种方法

    Node.js写文件的三种方式: 1.通过管道流写文件 采用管道传输二进制流,可以实现自动管理流,可写流不必当心可读流流的过快而崩溃,适合大小文件传输(推荐) var readStream = fs. ...

  8. Node.js 自学之旅(初稿篇)

    学习基础,JQuery 原生JS有一定基础,有自己一定技术认知(ps:原型链依然迷糊中.闭包6不起来!哎!) 当然最好有语言基础,C#,java,PHP等等.. 最初学习这个东西的原因很简单,在园子里 ...

  9. Node.js 蚕食计划(三)—— Express 启航

    如果看过上一篇<Node.js 蚕食计划>,就会发现手动搭建一个 web 服务器还是比较繁琐 而 express 就是一个可以极大地提高开发效率的 web 开发框架 一.创建项目 在 ex ...

随机推荐

  1. 在Asp.net MVC 3 web应用程序中,我们会用到ViewData与ViewBag,对比一下:

    Asp.net MVC中的ViewData与ViewBag ViewData ViewBag 它是Key/Value字典集合 它是dynamic类型对像 从Asp.net MVC 1 就有了 ASP. ...

  2. css:overflow属性妙用

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  3. ORA-00494: enqueue [CF] held for too long (more than 900 seconds) by 'inst 1, osid 5166'

    凌晨收到同事电话,反馈应用程序访问Oracle数据库时报错,当时现场现象确认: 1. 应用程序访问不了数据库,使用SQL Developer测试发现访问不了数据库.报ORA-12570 TNS:pac ...

  4. Java实现上传下载

    一.上传 二.下载 import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.Fi ...

  5. 2015-12-01 SQL查询语句基础

    1.查询全体学生的学号与姓名select sno,snamefrom student;3.查询全体学生的详细信息select *from student;4.查询全体学生的姓名及其出生年份select ...

  6. 项目实现不同环境不同配置文件-maven profile

    最近接触的项目都是在很多地方都落地的项目,需要支持不同的环境使用不同的配置文件.一直以来都以为是人工的去写不同的配置文件,手动的去修改运用的配置文件.感觉自己还是太low呀.maven的使用的还停留在 ...

  7. C++使用vector

    #include <iostream> #include <string> #include <vector> using namespace std; void ...

  8. codevs 3110 二叉堆练习3

    3110 二叉堆练习3 http://codevs.cn/problem/3110/ 题目描述 Description 给定N(N≤500,000)和N个整数(较有序),将其排序后输出. 输入描述 I ...

  9. Java正则表达式入门——转自RUNOOB.COM

    Java 正则表达式 正则表达式定义了字符串的模式. 正则表达式可以用来搜索.编辑或处理文本. 正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别. Java正则表达式和Perl的是最为相似 ...

  10. mysql Packet for query is too large (1185 > 1024)异常

    注:最近mysql一直提示如下错误 Packet for query is too large (1185 > 1024). You can change this value on the s ...