`
hadix
  • 浏览: 25727 次
  • 性别: 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异步编程是JavaScript在服务器端运行的一种技术,它基于Chrome V8引擎,以其事件驱动、非阻塞I/O模型而闻名,极大地提高了网络应用的效率和可扩展性。Node.js的核心特性之一就是它的异步处理能力,这使得...

    Node.js-StuQ分享专题《深入浅出jsNode.js异步流程控制》完整版

    本专题《深入浅出js(Node.js)异步流程控制》将探讨Node.js中的异步编程这一核心概念,帮助开发者更深入地理解和掌握这一技术。 异步编程是Node.js的核心特性之一,它允许程序在等待I/O操作完成时继续执行其他任务...

    Professional Node.js 高级编程 (英文pdf+源码)

    《Professional Node.js 高级编程》是一本由Pedro Teixeira编著的专业技术书籍,主要探讨了Node.js这一强大的JavaScript后端开发平台。这本书详细介绍了如何利用Node.js进行高效、高性能的应用程序开发,旨在帮助...

    Node.js开发-Node.js入门.pdf

    * 学习曲线陡峭: Node.js 的异步机制和事件驱动机制需要开发者具备一定的编程基础和经验。 * 不适合计算密集型应用程序: Node.js 不适合计算密集型应用程序,因为它的单线程模型限制了其计算性能。 Node.js 是一...

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

    但不管怎样,异步编程确实是 NodeJS 最大的特点,没有掌握异步编程就不能说是真正学会了 NodeJS。本章将介绍与异步编程相关的各种知识。 在代码中,异步编程的直接体现就是回调。异步编程依托于回调来实现,但不能说...

    Node.js By Example

    Node.js的核心特性包括单线程事件循环、异步编程、模块系统以及强大的文件系统操作等。在本书中,你将学习如何利用这些特性来开发高效的应用程序。 1. **事件驱动编程**:Node.js采用事件驱动模型,当有I/O操作时,...

    Node.js硬实战 115个核心技巧.pdf

    1. **异步编程**:Node.js的核心之一就是异步编程模型,这使得它能够处理大量并发请求,避免了阻塞I/O操作导致的性能瓶颈。书中会深入讲解回调函数、Promise、async/await等异步控制流技术。 2. **事件循环(Event ...

    node.js 安装包 10.16.3-x64

    Node.js 是一个开源、跨平台的JavaScript运行环境,它允许开发者在服务器端执行JavaScript代码,极大地拓宽了JavaScript的应用领域。10.16.3-x64 版本是 Node.js 的一个稳定版本,适用于64位操作系统。下面将详细...

    node.js实战 pdf+源码

    2. **异步编程**:Node.js的核心特性之一是其对异步编程的支持。通过回调函数、Promise和async/await等机制,开发者可以处理大量并发请求,避免了传统的多线程模型中的上下文切换开销。 3. **事件循环**:Node.js...

    node.js最新手册

    Node.js是一种基于Chrome V8引擎的JavaScript运行环境,它允许开发者在服务器端使用JavaScript进行编程。这个"Node.js最新手册"很可能包含了关于Node.js的最新API、模块系统、事件驱动模型以及异步I/O等内容。 在...

    Node.js 6.x Blueprints(pdf+epub+mobi+code)

    6. **性能优化**:探讨Node.js的性能监控、调试技巧以及优化策略,如异步编程、内存管理等。 7. **部署与维护**:讲解如何将Node.js应用部署到云平台,如Heroku、Docker,以及持续集成和持续部署(CI/CD)的实践。 8...

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

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

    《Node入门一本全面地Node.js教程》PDF

    6. **异步编程**: - **回调函数**:Node.js中的异步操作通常通过回调函数实现,但过度使用可能导致回调地狱问题。 - **Promise**:Promise是解决回调地狱的工具,提供了链式调用和错误处理机制。 - **async/...

    Node.js资料包,5本电子书籍

    2. 掌握异步编程和事件驱动模型。 3. 学会使用Express框架搭建Web应用。 4. 熟悉npm的使用,包括安装、发布和管理依赖。 5. 了解如何进行Node.js应用的测试和部署。 6. 应对实时通信需求,如WebSocket的应用。 7. ...

    pdf版,Node.js开发实战详解

    Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它让JavaScript开发者可以在服务器端执行代码,打破了传统的JavaScript只能在浏览器端运行的限制。这本《Node.js开发实战详解》电子书,显然是为了帮助那些...

    [英文] Node.js for PHP Developers

    回调函数是Node.js异步编程模型的核心,通过回调,Node.js能够在不阻塞主线程的情况下执行I/O操作。作者介绍了匿名函数、lambda表达式和闭包的概念,并将其与PHP 5.3和PHP 4中的相似功能进行了比较。 HTTP响应的...

    Node.js高级编程.pdf

    7. **Promise和async/await**:Node.js从版本7开始引入Promise,从版本8开始支持async/await,为异步编程提供了更优雅的解决方案,降低了回调地狱带来的复杂性。 8. **NPM(Node Package Manager)**:Node.js的包...

Global site tag (gtag.js) - Google Analytics