首页 > 其他分享 >lua版promise实现 - 结束

lua版promise实现 - 结束

时间:2024-08-16 23:50:29浏览次数:6  
标签:function end self lua State promise Promise 结束 local

相比V1版本这边做了以下修改:

1) 函数命名尽量与js版保持一致,js中的then在这边叫Next(因为then是lua的关键字)

2) m_DoNextObj这边变成了一个列表,这样改动的结果就是:之前对象间会组成单向链表;这边是一个单向的树。

3) m_DoNextObj.run函数这边改成了m_OnFulfilled和m_OnRejected函数(为了与js保持一致)

4) SetFinished函数改成了FulFulled和Reject函数

5) V1版本,Promise对象会作为参数传入run函数,需要手动调用SetFinished;这边全部封装在Promise内部自动完成;

 

Promise.lua

---@class Promise
local Promise = {}
Promise.__cname = "Promise"
Promise.__index = Promise

local State = {
    Pending = 0,
    FulFilled = 1,
    Rejected = -1,
}

------------------ 内部函数 ------------------

---@type Promise
local Inner = {}

local function OnFulFilled_Default(x)
    return x
end

local function OnRejected_Default(x)
    error(x)
end

local function IsCallbackResultPromise(result)
    if "table" == type(result) then
        local result = result.isPromise or "Promise" == result.__cname
        return result
    end
    return false
end

---@param prmNode Promise
---@param otherPrm Promise
function Inner.WaitOtherPromise(prmNode, otherPrm)
    if otherPrm:IsPending() then
        --[[ --这样会多创建一个临时Promise对象, 所以这边用下面的方式
        local tempPrm = otherPrm:Next(function(value)
            prmNode:FulFilled(value)
        end, function(reason)
            prmNode:Reject(reason)
        end)
        ]]
        --otherPrm作为子树的新Root
        prmNode.m_TransitStateFlag = true
        table.insert(otherPrm.m_NextList, prmNode)
    else
        Inner.TransitionState(prmNode, otherPrm.m_State, otherPrm.m_Value)
    end
end

function Inner:NextRun()
    local nextList = self.m_NextList
    local isFulFilled = (self.m_State == State.FulFilled)

    for i, v in ipairs(nextList) do
        local nextNode = nextList[i]
        if true == nextNode.m_TransitStateFlag then
            --callback被调用过了
            Inner.TransitionState(nextNode, self.m_State, self.m_Value)
        else
            local isSucc, result, promiseFlag
            if isFulFilled then
                isSucc, result, promiseFlag = pcall(nextNode.m_OnFulFilled, self.m_Value)
            else
                isSucc, result, promiseFlag = pcall(nextNode.m_OnRejected, self.m_Value)
            end
            if isSucc then
                if promiseFlag or IsCallbackResultPromise(result) then
                    Inner.WaitOtherPromise(nextNode, result)
                else
                    nextNode:FulFilled(result)
                end
            else
                print(debug.traceback(result, 1))
            end
        end
    end
    for i=#nextList,1,-1 do
        nextList[i] = nil
    end
end

function Inner:TransitionState(state, value)
    if self.m_State == state or self.m_State ~= State.Pending then
        return
    end

    self.m_State = state
    self.m_Value = value
    Inner.NextRun(self)
end

------------------

function Promise.new()
    local inst = {}
    setmetatable(inst, Promise)
    inst:ctor()
    return inst
end

function Promise:ctor()
    self.m_State = State.Pending
    self.m_Value = nil

    ---@type Promise[]
    self.m_NextList = {}

    self.m_OnFulFilled = OnFulFilled_Default
    self.m_OnRejected = OnRejected_Default
    self.m_TransitStateFlag = nil
end

---@param onFulFilled fun(value):any
---@param onRejected fun(reason):any
---@return Promise
function Promise:Next(onFulFilled, onRejected)
    local prmNode = Promise.new()
    prmNode.m_OnFulFilled = onFulFilled or OnFulFilled_Default
    prmNode.m_OnRejected = onRejected or OnRejected_Default

    table.insert(self.m_NextList, prmNode)
    if self.m_State ~= State.Pending then
        Inner.NextRun(self)
    end

    return prmNode
end

function Promise:FulFilled(result)
    if self.m_State == State.Pending then
        self.m_State = State.FulFilled
        self.m_Value = result

        Inner.NextRun(self)
    end
end

function Promise:Reject(reason)
    if self.m_State == State.Pending then
        self.m_State = State.Rejected
        self.m_Value = reason

        Inner.NextRun(self)
    end
end

---@return boolean, boolean isPending, isFulFilled
function Promise:GetState()
    local isPending = self.m_State == State.Pending
    local isFulFilled = self.m_State == State.FulFilled
    return isPending, isFulFilled
end

---@return boolean
function Promise:IsPending()
    return self.m_State == State.Pending
end

function Promise:GetValue()
    return self.m_Value
end

return Promise

 

一些使用例子

例1) 先加载A,再加载B,再加载C

local textList = {}
local resAPrm = LoadResAsync("ResA")

local prm1 = resAPrm:Next(function(textA)
    print("ResA load finish")
    table.insert(textList, textA)
    --a加载完, 加载b
    local resBPrm = LoadResAsync("ResB")
    return resBPrm
end)

local prm2 = prm1:Next(function(textB)
    --prm2收到的是resBPrm的值
    print("ResB load finish")
    table.insert(textList, textB)
    --b加载完, 加载c
    local resCPrm = LoadResAsync("ResC")
    return resCPrm
end)

local lastPrm = prm2:Next(function(textC)
    --lastPrm收到的是resCPrm的值
    table.insert(textList, textC)
    print(unpack(textList))
end)

执行链分析:

 

例2) A加载完同时加载B, C, D;B, C, D全部加载完,才加载E

 

关于LoadResAsync

---@type MsgLoop
local MsgLoop = require("MsgLoop")
local _MsgLoop = MsgLoop.new(60)

local function LoadResAsync(res)
    local connector = Promise.new()
    --假装加载资源
    _MsgLoop:PostRun(function(data)
        connector:FulFilled(data)
    end, 2, res)
    return connector
end


--逻辑代码写在StartLoop前
require("test.lua")

_MsgLoop:StartLoop()

MsgLoop参考这边:消息循环

 

标签:function,end,self,lua,State,promise,Promise,结束,local
From: https://www.cnblogs.com/sailJs/p/18351851

相关文章

  • lua版promise实现3 - 条件判断例子
    针对:先加载资源A,加载完A再加载资源B,加载完B再加载资源C。现在加需求了,如果加载资源A的时间不超过3s,那说明当前设备性能不错,会额外再加载高品质资源A2,A3,然后再加载B。 localobj1=PromiseV1.new()localtime1=os.time()AsyncLoadRes("ResA",function(textA)obj1:S......
  • 【电赛】第一次电赛省二结束
    第一次参加电赛以省二结束,对于这个成绩有满意也有遗憾,超声波换能器频率的选择失败和前期选材和队友沟通没做好,通了一个宵完成了这个粗糙的作品,明年国赛再战。以此篇作为纪念。      ......
  • 合宙Air780EP模组LuatOS脚本开发MQTT应用示例
    本文详细讲解了基于合宙Air780EP模组LuatOS开发的多个MQTT应用示例。本文同样适用于合宙的以下型号:Air780EPA/Air780EPT/Air780EPSAir780E/Air780EX/Air201…一、相关准备工作1.1硬件准备合宙EVB_Air780EP开发板一套,包括天线、SIM卡;USB线PC电脑1.2软件准备登录合宙......
  • openresty通过lua实现ip地址hash
    实验环境:root@paas-test-ubuntu:/opt/openresty#bin/openresty-Vnginxversion:openresty/1.25.3.2builtbygcc11.4.0(Ubuntu11.4.0-1ubuntu1~22.04)builtwithOpenSSL3.0.215Mar2022TLSSNIsupportenabledconfigurearguments:--prefix=/opt/openresty/n......
  • 运算符结束
    运算符逻辑运算packageoperator;//逻辑运算符publicclassDemo05{publicstaticvoidmain(String[]args){//与或非booleana=true;booleanb=false;System.out.println("a&&b"+(a&&b));//逻辑与运算:有假为......
  • 在C/C++中嵌入Lua代码及使用VS Code调试
     Lua在设计之初就是为了嵌入到应用程序中,为这些应用程序提供灵活的扩展和定制功能。Lua的核心是用C语言编写的,所以Lua脚本可以很容易地与C/C++代码进行交互,通过Lua脚本,用户可以在不修改原有C/C++代码的基础上,实现功能的扩展和定制。 在C/C++程序中可以使用Lua来编写一些需......
  • 点击识别按钮调用后端接口,中途按下结束识别,但是识别还是进行啦js
    在JavaScript中,如果你想要在点击按钮后调用一个接口,并且在这个过程中按下一个按钮来中断或取消这个请求,你可以使用fetchAPI来发起请求,并使用AbortController来取消这个请求。以下是一个简单的例子://获取按钮元素conststartButton=document.getElementById('startButton');......
  • js异步之Promise使用
    Promise是异步编程的一种解决方案,是一个对象,可以获取异步操作的消息,大大改善了异步编程的困难,避免了回调地狱,比传统的解决方案回调函数和事件更合理和更强大。从语法上讲,Promise是一个对象,它可以获取异步操作的消息。提供了一个统一的API,各种异步操作都可以用同样的方法进行处理......
  • lua版promise实现 - 从异步回调多层嵌套开始
    异步回调代码,很容易就写出下面这样的不断嵌套的代码。如果还夹杂着各种逻辑的话,可读性会很差,还容易出错。AsyncLoadRes("ResA",function(textA)print("ResAloadfinish")AsyncLoadRes("ResB",function(textB)print("ResBloadfinish")AsyncLoad......
  • Activiti配置工作流结束过程
    在工作流结束过程中,类里面配置工作流结束时的过程实现方法:publicclassUpdateStatusimplementsJavaDelegate,ApplicationContextAware{ privatestaticApplicationContextapplicationContext; /** *采购审核结果处理 *@paramexecution */ @Override publ......