2013-06-13 97 views
1

我工作了很多與Lua和科羅娜SDK,而我喜歡它作爲一種語言,我已經意識到我的代碼可以得到相當凌亂回調調用回調等。避免Lua的回調地獄

我想知道是否有任何設計模式或庫(如JavsScript的async.js)有助於減少問題。

一個典型的例子將是電暈的過渡呼叫使用:

transition.to(obj,{... onComplete=function() 
    transition.to(obj,{... onComplete=function() 
     if foo then 
      transition.to(obj,{... onComplete=function() ... end}) 
     else 
      transition.to(obj,{... onComplete=function() ... end}) 
     end 
    end}) 
end}) 

我發現代碼很快變得相當密集,但往往內關閉依賴於來自外部的變量。我明白,自律是創建廉潔代碼的重要因素,但有一個強制使用自律的結構是有用的。除了命名關閉之外,任何人都會遇到一種有效的管理方式?

+0

只需申報對象的所需場景的起點,使過渡爲功能(如果它們是相同的),並調用該函數在需要時... –

+1

是你的問題的表現或只是編碼風格?如果它的性能,你不能做太多的事情,因爲這是科羅納SDK的工作方式。 –

+0

協程可能可以在這裏做這個工作 – Eric

回答

2

使用協同程序可能有助於在這裏:​​

await = function(f) 
    return function(...) 
     local self = coroutine.running() 
     f(..., {onComplete=function(...) 
      coroutine.resume(self, ...) 
     end}) 
     return coroutine.yield() 
    end 
end 

await(transition.to)(obj) 
await(transition.to)(obj) 
if foo then 
    await(transition.to)(obj) 
else 
    await(transition.to)(obj) 
end 

或者更一般地,解決的意見問題:

async_call = function(f) 
    local self = coroutine.running() 
    local is_async 
    local results = nil 
    local async_continue = function(...) 
     if coroutine.running() ~= self then 
      is_async = true 
      coroutine.resume(self, ...) 
     else 
      is_async = false 
      results = {...} 
     end 
    end 
    f(async_continue) 
    if is_async then 
     return coroutine.yield() 
    else 
     return unpack(results) 
    end 
end 

async_call(function(cont) transition.to(obj, {onComplete=cont}) end) 
+0

我覺得你剛剛暴露我的Lua的協程的無知可恥的過渡通話可能會有點整潔。這迫使我再次在Lua中編程的那一章。 – personalnadir

+0

@personalnadir:我沒有聲稱這將實際上工作。有一件事會導致它失敗,如果在返回之前'f'實際調用'onComplete'。 – Eric

+0

感謝您的例子!原來,從回調的onComplete中調用coroutine.yield打破了元方法/ C-呼叫界限。但我寫的協同程序的一個簡單的簡單堆疊系統會根據你的第一個例子中有我的角色的方式。 – personalnadir

0

的一種方法是定義回調作爲一個全球性的或的upvalue並注入通過將回調包裝在另一個功能中,回調所需的高價值:

function foo(upvalue) 
    return function(...) -- thats the actual callback 
     return print(upvalue, ...); 
    end 
end 

然後,你可以附上它作爲一個回調像

transition.to(obj,{... onComplete=foo(somevar)}) 

的附加功能調用但會對性能有一些小的影響。另一方面,如果你有多個類似的回調,你可能會想出一些代碼重用。

相關問題