您的位置:首页 > Web前端 > Node.js

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

2013-10-29 16:32 531 查看
[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) 顺序执行逻辑不同的异步函数

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

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

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

       

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

第一个异步函数的处理结束后才能调用第二个(异步)函数
这种情况下,也是层层回调,但是回调函数本身只是调用下一个异步函数,目的只是为了保证顺序执行。比如需要处理文件,先读取下日志并保存,然后排序合并。然后删除原始日志,排序合并必须在日志都读取保存完成后,而删除必须在合并完成后,这就是一种必须的顺序执行,否则数据就会不准确。大体框架如下:

# 定义三个函数fun*
fun1 = (_parms1, _cb)-> ...
fun2 = (_parm2, _cb)-> ...
fun3 = (_parm3)-> ...
...# 调用处理,定义了两个函数直接调用下一步的函数,并用作回调函数_funcb2 = -> fun3 _parms3_fun1cb = -> fun2 _parms2, _funcb2fun1 _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  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息