一、API介绍


框架提供内置的异步库cf, 需要使用的时候我们必须先导入: local cf = require "cf".

1. 超时定时器


函数原型: cf.timeout(timeout, callback)

第一个参数timeout为超时时间(秒), 第二个参数callback为超时后触发的回调函数;

调用此方法将会返回一个timer对象, 对象拥有stop方法可用来提前停止它;

如果你不需要提前停止可用忽略它, 但请不要在外部修改次对象的任何属性; 否则会得到意外的行为;

超时定时器为开发者提供了对时间事件的控制能力; 它是一次性的, 在回调函数触发之后将会自动停止运行;

应用场景, 例如: 网络连接超时一次性任务.

注意: 此方法不会阻塞当前协程.

2. 循环定时器


函数原型: cf.at(timeout, callback)

第一个参数timeout为循环时间(秒), 第二个参数callback为超时后触发的回调函数;

调用此方法将会返回一个timer对象, 对象拥有stop方法可用来提前停止它;

如果你不需要提前停止可用忽略它, 但请不要在外部修改次对象的任何属性; 否则会得到意外的行为;

循环定时器为开发者提供了对时间事件的控制能力; 它对时间重复的任务中会经常用到;

应用场景, 例如: 定期心跳检查循环定时任务.

注意: 此方法不会阻塞当前协程.

3. 休眠定时器


函数原型: cf.sleep(timeout)

参数timeout为休眠时间, 此方法不会有返回值; 此方法的行为取决于传入的timeout

  • timeout > 0的时候; 当前协程会暂停并且让出执行权, 直到超时时间来临后被唤醒;

  • timeout = 0的时候; 当前协程会暂停并且让出执行权. 没有其它协程或者其它协程任务完成后会被"立刻唤醒".

  • timeout < 0type(timeout) ~= ’number 的时候; 此方法不会做任务动作并且直接返回.

    应用场景, 休眠函数一般不会在方法内独自存在, 一般会搭配其他异步方法配合完成任务;

    注意: 此方法将会阻塞当前协程直到休眠时间到达, 但是并不会阻塞进程与事件调度器.

4. 可调度协程


函数原型: cf.fork(callback, ...)

当需要异步执行一个函数的时候, 可以使用cf.fork创建一个有框架来调度的协程. 此方法会返回一个coroutine对象.

cf库提供(补充)了协程管理的所有方法. 与Lua的原生协程不同的是, cf在原生协程的基础上加入了生命周期管理.

第一个参数callbackfunction类型, 后面的所有参数会作为参数传入到callback中.


函数原型: cf.self()

此方法用于获取当前协程对象, 此对象不一定是可被框架调度的协程.


函数原型: cf.wait()

此方法用于暂停当前协程并且让出执行权; 此方法没有参数, 返回值的内容与类型由cf.wakeup决定.


函数原型: cf.wakeup(coroutine, ...)

此方法用于唤醒cf.wait暂停的协程; 此方法没有返回值, coroutine对象之后的所有参数将会返回给cf.wait进行接收.

5. 异步文件


框架内部实现了aio库; 与内置的io库不同的是, 它是基于异步I/O改造而来. 通过高效的异步队列来完成阻塞任务.

aio内部将异步回调改造成为同步非阻塞, 在等待事件之外不会阻塞进程(阻塞当前协程). 提升了框架的整体执行效率.

下面我们来看一些常见的异步文件操作接口:


函数原型:aio.create(filename)

此方法将会创建一个filename文件;

创建成功返回__AIO__对象, 否则返回nil与出错信息(文件已存在).


函数原型:aio.open(filename)

此方法将会打开(不存在则创建)一个filename文件;

打开成功返回__AIO__对象(无论是否存在), 否则返回nil与出错信息(例如: 没有操作权限).


函数原型:aio.stat(path)

此方法将返回path参数所在文件/文件夹内部属性;

返回值是一个table类型字典值, 内部包含了/文件夹的各种属性.


函数原型:aio.dir(path)

此方法将返回path参数所在目录下所有文件与文件夹名称;

返回值是一个table类型数组值, 数组是文件与文件夹名称(字符串).


函数原型:aio.rmdir(dir)

此方法将删除dir参数目录;

返回值是一个boolean类型值, 这个返回值表示删除是否成功.


函数原型:aio.mkdir(dir)

此方法将创建dir参数目录;

返回值是一个boolean类型值, 这个返回值表示创建是否成功.


函数原型:aio.rename(old_name, new_name)

此方法会将old_name的文件名称改为new_name.

返回值为true表示修改成功, 其他都表示修改失败.


函数原型:aio.currentdir(path)

此方法将获取path参数指定的文件/文件夹完整路径.

返回值为string类型, 内容为当前path参数指定的文件/文件夹完整路径.


函数原型:aio.truncate(filename, offset)

此方法将filename参数指向的文件进行扩容缩容.

在磁盘容量与文件存在的情况下, 此方法永远会返回true;

需要注意的是: "这个操作非常危险, 除非你明确知道你在做什么"; offset为0表示清空文件内容.

二、开始实践


1. 每秒输出随机数


我们首先修改随机数生成器种子, 然后启动一个循环定时器开始每隔一秒打印一个随机数.

-- script/main.lua
local cf = require "cf"
local LOG = require "logging"

math.randomseed(os.time())

cf.at(1, function ( ... )
  LOG:DEBUG(math.random())
end)
[candy@MacBookPro:~/cfadmin] $ ./cfadmin
[2020-09-06 13:43:30,373] [@script/main.lua:8] [DEBUG] : 0.16541362740099
[2020-09-06 13:43:31,376] [@script/main.lua:8] [DEBUG] : 0.45016892394051
[2020-09-06 13:43:32,376] [@script/main.lua:8] [DEBUG] : 0.99273784598336
[2020-09-06 13:43:33,375] [@script/main.lua:8] [DEBUG] : 0.57199324760586
[2020-09-06 13:43:34,375] [@script/main.lua:8] [DEBUG] : 0.087855347432196
[2020-09-06 13:43:35,377] [@script/main.lua:8] [DEBUG] : 0.18002282595262
[2020-09-06 13:43:36,377] [@script/main.lua:8] [DEBUG] : 0.97659156890586
[2020-09-06 13:43:37,373] [@script/main.lua:8] [DEBUG] : 0.22568983258680
^C
[candy@MacBookPro:~/cfadmin] $

可以看到, 每次的输出不同内容的随机数.

2. 定时器的启动与暂停


循环定时器的启动与停止必然是成对存在的. 下面的代码示例展示了定时器的启动与停止

-- script/main.lua
local cf = require "cf"
local LOG = require "logging"

local co = cf.self()

local timer
local index = 1
timer = cf.at(1, function ( ... )
  LOG:DEBUG("index = " .. index )
  index = index + 1
  if index > 3 then
    cf.wakeup(co)
    timer:stop()
  end
end)

cf.wait()

LOG:DEBUG("over.")

控制台输出结果:

[candy@MacBookPro:~/cfadmin] $ ./cfadmin
[2020-09-06 13:55:13,224] [@script/main.lua:10] [DEBUG] : "index = 1"
[2020-09-06 13:55:14,224] [@script/main.lua:10] [DEBUG] : "index = 2"
[2020-09-06 13:55:15,224] [@script/main.lua:10] [DEBUG] : "index = 3"
[2020-09-06 13:55:15,224] [@script/main.lua:20] [DEBUG] : "over."
[candy@MacBookPro:~/cfadmin] $

在上述这段代码中, 我们启动了一个循环定时器并且获取了一个timer的对象.

主协程暂停后切换到定时任务, 在定时任务结束后唤醒主协程打印最后结果.

3. 协程之间的互相作用


-- script/main.lua
local cf = require "cf"
local LOG = require "logging"
local co = cf.self()

LOG:DEBUG("主协程开始运行..")

cf.fork(function ()
  LOG:DEBUG("cf协程开始运行..")
  local result = 0
  for index = 1, 100 do
    result = result + index
  end
  LOG:DEBUG("cf协程运行完毕, 返回结果并且唤醒主协程..")
  return cf.wakeup(co, result)
end)

LOG:DEBUG("主协程休眠等待计算完成..")
local result = cf.wait()
LOG:DEBUG("主协程休眠结束获取到结果为:"..result)
LOG:DEBUG("主协程执行完毕..")
[candy@MacBookPro:~/cfadmin] $ ./cfadmin
[2020-09-06 13:59:44,452] [@script/main.lua:6] [DEBUG] : "主协程开始运行.."
[2020-09-06 13:59:44,453] [@script/main.lua:18] [DEBUG] : "主协程休眠等待计算完成.."
[2020-09-06 13:59:44,453] [@script/main.lua:9] [DEBUG] : "cf协程开始运行.."
[2020-09-06 13:59:44,453] [@script/main.lua:14] [DEBUG] : "cf协程运行完毕, 返回结果并且唤醒主协程.."
[2020-09-06 13:59:44,453] [@script/main.lua:20] [DEBUG] : "主协程休眠结束获取到结果为:5050"
[2020-09-06 13:59:44,453] [@script/main.lua:21] [DEBUG] : "主协程执行完毕.."
[candy@MacBookPro:~/cfadmin] $

4. 对文件进行异步操作

我们首先创建一个文件 - mytest.txt

-- script/main.lua
local aio = require "aio"

print(aio.create("mytest.txt"))
[candy@MacBookPro:~/cfadmin] $ ./cfadmin
__AIO__: 0x7ffcb5414850
[candy@MacBookPro:~/cfadmin] $

我们用下面的代码写入内容: Hello! Welcome to used aio.

-- script/main.lua
local aio = require "aio"

local afile, err = aio.open("mytest.txt")
if not afile then
  return print(afile, err)
end

print(afile:write("Hello! Welcome to used aio."))
[candy@MacBookPro:~/cfadmin] $ ./cfadmin
27  nil
[candy@MacBookPro:~/cfadmin] $

我们用afile:readall将我们刚刚写入的内容全部读取出来

-- script/main.lua
local aio = require "aio"

local afile, err = aio.open("mytest.txt")
if not afile then
  return print(afile, err)
end

print(afile:readall())
[candy@MacBookPro:~/cfadmin] $ ./cfadmin
Hello! Welcome to used aio.
[candy@MacBookPro:~/cfadmin] $

现在使用afile:clean清空文件所有内容

-- script/main.lua
local aio = require "aio"

local afile, err = aio.open("mytest.txt")
if not afile then
  return print(afile, err)
end

print(afile:clean())
[candy@MacBookPro:~/cfadmin] $ ./cfadmin
true
[candy@MacBookPro:~/cfadmin] $

最后, afile对象需要主动调用afile:close()手动释放资源.

三、继续学习


本章我们学会了一些内置的一些异步方法, 下一章我们将学习如何使用MQ库.

Copyright © CandyMi 2019-2022 all right reserved,powered by Gitbook该文件修订时间: 2021-05-12 10:40:18

results matching ""

    No results matching ""