nodejs异步非阻塞IO及实例(cs)

[node-sync is a simple library that allows you to call any asynchronous function in synchronous way.]


    nodejs的最大特点,事件驱动,异步非阻塞,有且只有一个线程。

(1)异步的初步理解

nodejs包含大量异步过程和回调函数(callback),下面的代码实现了ls的功能。

# functions like ls command
# result <filenames of ./> <end> <filenames of ./>

fs = require 'fs'

filenames = fs.readdirSync '.'
for filename in filenames
  console.log filename

fs.readdir '.', (_err, filenames)->
  for filename in filenames
    console.log filename

console.log 'end'

 
 
可以看到,上面代码先调用了同步的readdir函数读取当前路径下的filename。nodejs官方文档中,fs一节有很多file的同步实现函数及对应非同步函数,链接: http://nodejs.org/api/fs.html  。异步情况下,应用程序会进行下一个函数,而不会等待回调函数结束,这就是所谓的异步非阻塞。

PS:如果我们需要使用异步函数的结果,必须在回调函数中调用

(2) 顺序执行逻辑不同的异步函数

这种情况较为多见,一般分为两种情况:

  • 第一个异步函数的结果是第二个(异步)函数的参数

         这种情况比较简单,只需要层层回调就可以了,大体框架如下:

       

 
 
# 定义异步函数fun1
fun1 = (_parms, _cb)->
...
...
# 调用fun1,后面定义回调函数对fun1的数据进行处理
fun1 _parms, (_data)->
...

  • 第一个异步函数的处理结束后才能调用第二个(异步)函数
这种情况下,也是层层回调,但是回调函数本身只是调用下一个异步函数,目的只是为了保证顺序执行。比如需要处理文件,先读取下日志并保存,然后排序合并。然后删除原始日志,排序合并必须在日志都读取保存完成后,而删除必须在合并完成后,这就是一种必须的顺序执行,否则数据就会不准确。大体框架如下:
  
  
# 定义三个函数fun*
fun1 = (_parms1, _cb)->
...
fun2 = (_parm2, _cb)->
...
fun3 = (_parm3)->
...
...
# 调用处理,定义了两个函数直接调用下一步的函数,并用作回调函数
_funcb2 = -> fun3 _parms3
_fun1cb = -> fun2 _parms2, _funcb2
fun1 _parms1, _fun1cb
上面的cb函数必须在fun1前定义,但执行是从fun1开始的,它执行完成再调用_fun1cb,它又会执行fun2函数,完成后调用_funcb2,这样就满足了上面顺序执行的需求。

(3)顺序执行逻辑相同异步函数

执行逻辑相同的异步函数时,上面(2)中的层层调用的方法并不优雅,但同一般写法不同,这时nodejs使用while,break语句会报错。此时,可以使用函数嵌套函数的方法。例子如下:

# Don't try to do this with 'while' and 'break'
# This's a example of asynchronous function nested asynchronous function

http = require "http"

# 获取某url的数据
getdata = (_url, _callback) ->
  http.get _url, (_res)->
    _body = ""
    _res.on 'data', (_chunk) ->
      _body += _chunk
    _res.on 'end', ->
      try
        _stat = JSON.parse _body
      catch _e
        process.stderr.write _e
        process.exit 1
      if not _callback
        console.log _stat
      else
        _callback _stat
  " "

# 获得多个url的数据
request = (_urls, _ret, _callback = null)->
  _url = _urls.shift()
  getdata _url[1], (_data)->
    _ret[_url[0]] = _data
    _callback = console.log if not _callback
    return _callback _ret if _urls.length is 0
    request _urls, _ret, _callback

module.exports = {getdata, request}

 
 
getdata是通过url获取页面数据的方法,当我们有一组urls时,可以调用request方法来获取数据。

request方法中,获取的data存在_ret中,并作为参数传递给再次调用的request函数直到urls遍历完成。


参考:http://www.ruanyifeng.com/blog/2013/10/event_loop.html  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值