`
hadix
  • 浏览: 25238 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论
阅读更多

        ajax的盛行,使javascript成为前端开发人员的宠儿.现今js已经可以通过nodejs在服务器运行.本文将通过对一段代码的逐渐改进来展示如何让程序员使用javascript快乐得进行非阻塞异步编程.nodejs和mongodb的具体安装和使用方法请参考文章最后的参考文献列表.

 

Hello,Node !

        nodejs是编程就绪的,任何功能都要通过编程实现.这和Tomcat,ApacheHTTP等运行就绪服务不同,后者安装后可以直接运行就可以通过浏览器访问.而nodejs起码要有如下代码.

var http = require('http');

http.createServer(function(req,resp){
  resp.end('Hello , Node !');
}).listen(8124);

console.log('server startup');

将这些代码保存为hellonode.js然后在命令行执行node hellonode.js.在浏览器通过http://localhost:8124/即可访问该服务,浏览器窗口会显示"Hello , Node !"字样.这段代码的意义很容易理解,开头的require相当于java中的import将http模块引入,后面使用http模块的API构建http服务.javascript回调用来处理收到的请求,并返回字符串给浏览器.

 

一个稍微复杂的例子

        现实环境中,常规得处理http请求的过程大概是这样的.首先,服务器收到请求并从中解析出请求参数,然后使用这些参数进行数据库查询,最后将得到的结果放入模板生成视图响应给用户.伪代码大概如下这个样子.

 

var http = require('http');
var queryString = require('queryString');
var url = require('url');

var db = {};//初始化数据库

http.createServer(function (req, resp) {
  //1.解析请求参数
  var params = queryString.parse(url.parse(req.url).query);
  var template = 'result = _';
  //2.使用参数查询数据
  db.query(params, function (err, result) {
    //3.在回调中使用查询结果
    if (err) throw err;
    var view = template.replace(/_/, result);
    //4.返回视图,响应给客户端
    resp.end(view);
  });
}).listen(8124);

console.log('server startup');

 

 

变得更复杂

可以看到代码(2)部分由于数据库查询在node中是无阻塞的,所以必须将所有后续处理查询结果的代码作为回调来使用,上面代码的处理过程比较简单,但是如果放入真实的应用中,不一定如此,比如模板要根据请求参数从本地文件系统加载.代码就会变为如下样子.

 

var http = require('http');
var queryString = require('queryString');
var url = require('url');
var fs = require('fs');

var db = {};//初始化数据库

http.createServer(function (req, resp) {
  //解析请求参数
  var params = queryString.parse(url.parse(req.url).query);
  //使用参数查询数据
  db.query(params, function (err, result) {
    //在回调中使用查询结果
    if (err) throw err;
    fs.readFile(params.path, function (err, template) {
      if (err) throw err;
      //填充模板
      var view = template.replace(/_/, result);
      //返回
      resp.end(view);
    })
  });
  resp.end('Hello , Node !');
}).listen(8124);

console.log('server startup');

 

 

深层嵌套问题

 可以看到由于异步编程所以难免产生了又一层的嵌套回调.可以想想当处理过程更复杂的时候,会产生像如下的深层嵌套问题.

setp1(function (err, result1) {
  setp2(result1, function (err, result2) {
    setp3(result2, function (err, result3) {
      step4(result3, function (err, result4) {
        //更多的嵌套回调
      })
    })
  })
});

 

 

事件模型和Promise 

这样代码的编写阅读都非常困难.好在现在有许多编程模型可以解决这个问题,例如事件模型(发布订阅).

 

 

 

//注册事件监听器
server.on('connection', function (stream) {
  console.log('someone connected!');
});

//当如下代码被调用时上面的注册回调将被调用
server.emit('connection')//发布事件

 不过这样有一个问题,可以想象如果将上面的深层嵌套用这种方式编写,需要发布四次事件和注册四次监听器.本来一段内聚的代码会变得相当松散,依然没有根本解决读写理解困难的问题.下面介绍Promise模型.大概可以这样理解,每当异步处理执行时,总是返回一个Promise,该Promise保证在处理完成或发成错误时才调用后续的方法.Promise通常有这样的API.

 

 

promise.then(success,failure)

success,failure分别表示promise承诺的处理成功或失败时的回调函数.

 

上面的深层嵌套用该模型重写即可变为如下形式

 

step1().then(step2).then(step3).then(step3)

 这样就容易理解多了.要使用Promise模型,需要想node中引入支持库,我们使用'q'这个模块.可以使用npm install q进行安装.'q'这个模块提供了很多工具方法来将普通的回调转换为Promise.使用'q'改写最上面的请求处理,伪代码如下:

 

 

var http = require('http');
var queryString = require('queryString');
var url = require('url');
var fs = require('fs');
var q = require('q');

var db = {};//初始化数据库

http.createServer(function (req, resp) {
  //解析请求参数
  var params = queryString.parse(url.parse(req.url).query);
  //q.all将数组中的promise合并
  q.all([
          //q.ninvoke将原本的回调式调用转化为返回Promise对象
          q.ninvoke(db, 'query', params),
          q.ninvoke(fs, 'readFile', params.path)
        ])
    //当上述两个promise都处理完成时继续调用
    .then(function (result) {
            //返回结果为一个数组,数组中分别存放上面被组合的promise的结果
            var model = result[0];
            var template = result[1];
            var view = template.replace(/_/, model);
            resp.end(view);
          });
}).listen(8124);

console.log('server startup');

 这样看起来就容易理解多了,但问题是内部细节很难懂.好在有'q'这样的库帮帮我们处理.

 

 

使用CoffeeScript让代码变得更紧凑

javascript是一门古老的语言,不免语法冗余了点儿,好在现在有coffeescript这类的简单语言可以编译为javascript来运行.使用coffee来改写上面代码,就更加紧凑了.

http.createServer (req, resp)->
  param = queryString.parse(url.parse(req.url).query)
  q.all([ q.ninvoke(db, 'query', params),
          q.ninvoke(fs, 'readFile', params.path)])
    .then((result)->
           model = result[0]
           template = result[1]
           view = template.replace(/_/, modle)
           resp.end view)
console.log 'server startup'

 

 

参考文献

Node.js究竟是什么?

Node.js API

node/q 项目

CoffeeScript

javascript异步编程的4种方法

JavaScript异步编程的Promise模式

 

分享到:
评论

相关推荐

    Node.js异步编程

    Node.js异步编程

    Node.js 异步编程之 Callback介绍(一)

    Node.js 采用了与通常 Web 上的 JavaScript 异步编程的方式来处理会造成阻塞的I/O操作。在 Node.js 中读取文件、访问数据库、网络请求等等都有可能是异步的。对于 Node.js 新人或者从其他语言背景迁移到 Node.js 上...

    Node.js开发实战详解源代码

    涵盖的主要内容有:Node.js的概念、应用场景、环境搭建和配置、异步编程;Node.js的模块概念及应用、Node.js的设计模式;HTTP简单服务的搭建、Node.js静态资源管理、文件处理、Cookie和Session实践、Crypto模块加密...

    Node.js 开发指南.pdf

    目 录 第1章 Node.js简介 1 1.1 Node.js是什么 2 1.2 Node.js能做什么 3 1.3 异步式I/O与事件驱动 4 1.4 Node.js的性能 5 1.4.1 Node.js架构简介 5 1.4.2 Node.js与...附录B Node.js编程规范 167

    node.js开发指南(随书源码)

    Node.js是一种方兴未艾的新技术,诞生于2009年。... 而本书的目的就是帮助读者扫清这些障碍,学会使用Node.js进行Web后端开发,同时掌握事件驱动的异步式编程风格,以便进一步利用Node.js的高级特性。

    剖析Node.js异步编程中的回调与代码设计模式

    主要介绍了Node.js异步编程中的回调与代码设计模式,虽然大多数场合回调编写时的长串括号不怎么好看,但Node的异步性能确实很好,需要的朋友可以参考下

    《深入浅出Node.js》:Node异步编程解决方案之事件发布-订阅模式.docx

    《深入浅出Node.js》:Node异步编程解决方案之事件发布-订阅模式.docx

    Node.js开发指南-课件和源代码.rar

    该资源提供了关于Node.js开发的详细指南,涵盖了Node.js的基础知识、核心模块、异步编程、Web开发、数据库访问等内容。 适用人群:该资源适用于想要学习和掌握Node.js开发的开发人员和学习者。无论是初学者还是有...

    Node.js+开发指南

    目 录 第1章 Node.js简介 1 1.1 Node.js是什么 2 1.2 Node.js能做什么 3 1.3 异步式I/O与事件驱动 4 ...1.4 Node.js的性能 5 ...1.4.1 Node.js架构简介 5 ...附录B Node.js编程规范 167

    Node.js高级编程 PDF电子书下载 带书签目录 完整版

    本书是一本 Node.js 的入门教程,写给想了解 Node.js 的...过阅读本书,学会使用 Node.js 进行 Web 后端开发,同时能熟悉事件驱动的异步式编程风格, 以便进一步了解 Node.js 的许多高级特性,以及它所应用的更多领域

    node.js开发指南

    Node.js是一种方兴未艾的新技术,诞生于2009年。... 而本书的目的就是帮助读者扫清这些障碍,学会使用Node.js进行Web后端开发,同时掌握事件驱动的异步式编程风格,以便进一步利用Node.js的高级特性。

    Node.js Web开发实战-(共14章)PPT.rar

    第4章 异步编程与包管理.ppt 第5章 http模块.ppt 第6章 Web开发中的模板引擎.ppt 第7章 Node.js中的文件操作.ppt 第8章 认识express模块.ppt 第9章 MySQL数据库.ppt 第10章 Express框架.ppt 第11章 socket.io 模块....

    node.js 开发指南(详细)

    我的目标是使读者通过阅读本书,学会使用 Node.js 进行 Web 后端开发,同时能熟悉事件驱动的异步式编程风格,以便进一步了解 Node.js 的许多高级特性,以及它所应用的更多领域。 本书共6章,分别讨论了 Node.js 的...

    深入浅出node.js 田永强著

    深入浅出node.js,田永强著,清晰版,67页。node.js 是js运行平台,它采用事件驱动、异步编程,为网络服务而设计。

    Node.js从入门到精通

    本书是一本node.js的入门教程,写给想了解node.js的开发人员。读者通过阅读本书,学会使用node.js进行web后端开发,同时能熟悉事件驱动的异步式编程风格,进一步了解node.js的高级特性,以及它所应用的更多领域。

    Node.js编程资料汇总

    资源名称:Node.js编程资料汇总资源目录:【】fabian_frank_nodejs_velocity【】Nodejs,脱离了浏览器的Javascript(袁锋)_files【】nodejs手册中文【】NodeJS的异步编程风格【】Oreilly.Learning.Node.Aug.2012...

Global site tag (gtag.js) - Google Analytics