lua版promise实现2 - 从异步回调多层嵌套开始
异步回调代码,很容易就写出下面这样的不断嵌套的代码。如果还夹杂着各种逻辑的话,可读性会很差,还容易出错。
先加载资源A,加载完A再加载资源B,加载完B再加载资源C。
AsyncLoadRes("ResA", function(textA) print("ResA load finish") AsyncLoadRes("ResB", function(textB) print("ResB load finish") AsyncLoadRes("ResC", function(textC) print("ResC load finish") print(textA, textB, textC) end) end) end)
接下来把上面的多层嵌套优化下
回调内不直接写逻辑,而是调用对象的doNext函数
local obj1 = { value = nil, doNext = nil } AsyncLoadRes("ResA", function(textA) obj1.value = textA obj1.doNext(textA)
obj1.doNext = nil end) local obj2 = { value = nil, doNext = nil } obj1.doNext = function(textA) print("ResA load finish") AsyncLoadRes("ResB", function(textB) obj2.value = textB obj2.doNext(textB)
obj2.doNext = nil end) end local obj3 = { value = nil, doNext = nil } obj2.doNext = function(textB) print("ResB load finish") AsyncLoadRes("ResC", function(textC) obj3.value = textC obj3.doNext(textC)
obj3.doNext = nil end) end obj3.doNext = function(textC) print("ResC load finish, all loaded") end
再把上面的代码调整下
doNext改成了含有run方法的对象,objX.doNext(xxx)改成objX.doNextObj.run(textA)
local obj1 = { value = nil, doNextObj = nil } AsyncLoadRes("ResA", function(textA) obj1.value = textA obj1.doNextObj.run(textA, obj1.doNextObj)
obj1.doNextObj = nil end) local obj2 = { value = nil, doNextObj = nil } obj2.run = function(textA, _obj2) print("ResA load finish") AsyncLoadRes("ResB", function(textB) obj2.value = textB obj2.doNextObj.run(textB, obj2.doNextObj)
obj2.doNextObj = nil end) end obj1.doNextObj = obj2 local obj3 = { value = nil, doNextObj = nil } obj3.run = function(textB, _obj3) print("ResB load finish") AsyncLoadRes("ResC", function(textC) obj3.value = textC obj3.doNextObj.run(textC, obj3.doNextObj)
obj3.doNextObj = nil end) end obj2.doNextObj = obj3 local obj4 = { value = nil, doNextObj = nil } obj4.run = function(textC, _obj4) print("ResC load finish, all loaded") end obj3.doNextObj = obj4
为什么要这么改?
因为这样改之后,obj之间就组成了一个单向链表,这样比单纯用函数会灵活很多。
对上面的代码稍微封装下,就可以得到第1版的promise
---@class PromiseV1 local PromiseV1 = {} PromiseV1.__cname = "Promise" PromiseV1.__index = PromiseV1 function PromiseV1.new() local inst = {} setmetatable(inst, PromiseV1) inst:ctor() return inst end function PromiseV1:ctor() self.m_Value = nil self.m_IsFinish = false self.m_DoNextObj = nil self.m_Run = nil end function PromiseV1:Next(run) local obj = PromiseV1.new() obj.m_Run = run self.m_DoNextObj = obj return obj end function PromiseV1:SetFinished(v) if not self.m_IsFinish then self.m_IsFinish = true self.m_Value = v if self.m_DoNextObj then self.m_DoNextObj.m_Run(v, self.m_DoNextObj) self.m_DoNextObj = nil end end end
用法
local obj1 = PromiseV1.new() AsyncLoadRes("ResA", function(textA) obj1:SetFinished(textA) end) local loadResB = function(textA, _obj2) print("ResA load finish") AsyncLoadRes("ResB", function(textB) _obj2:SetFinished(textB) end) end local obj2 = obj1:Next(loadResB) local loadResC = function(textB, _obj3) print("ResB load finish") AsyncLoadRes("ResC", function(textC) _obj3:SetFinished(textC) end) end local obj3 = obj2:Next(loadResC) local printContent = function(textC, _obj4) print("ResC load finish, all loaded") end local obj4 = obj3:Next(printContent)
分类:
lua
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
2022-08-14 最简单的不受光(unlit)shader