Lua Academy · Lektion

xpcall och meddelandehanterare

Använd xpcall med en anpassad hanterare för detaljerade felspårningar.

Lektion 3 av 412 steg

xpcall och meddelandehanterare är en gratis lektion i Lua Academy på CoddyKit. Detta är lektion 3 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Lua Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Lua Academy innehåller totalt 4 lektioner.

xpcall-syntax

xpcall(f, handler, ...) anropar f med argumenten ... i skyddat läge och anropar vid fel handler(errorObject). Hanterarens returvärde blir xpcalls andra returvärde. Till skillnad från pcall kör xpcall hanteraren medan stacken fortfarande är intakt.

local function handler(err)
  return "HANDLED: " .. tostring(err)
end

local ok, msg = xpcall(
  function() error("something bad") end,
  handler
)

print(ok)   -- false
print(msg)  -- HANDLED: ...: something bad

debug.traceback som hanterare

Den vanligaste xpcall-hanteraren är debug.traceback. Skicka den direkt som hanterare — den formaterar felet med en fullständig anropsstackspårning, vilket är ovärderligt vid felsökning av fel i produktionsmiljö.

local function level3() error("deep error") end
local function level2() level3() end
local function level1() level2() end

local ok, err = xpcall(level1, debug.traceback)

if not ok then
  -- err contains the full stack trace
  print(err)
end

Anpassad hanterare med sammanhang

En anpassad hanterare kan lägga till sammanhang: tidsstämpel, loggning till fil och avisering till övervakningssystem, och därefter returnera det formaterade felet. Detta är standardmönstret för felhantering i Lua-applikationer i produktionsmiljö.

local function errorHandler(err)
  local trace = debug.traceback(err, 2)
  local ts = os.date("%H:%M:%S")
  local report = string.format("[%s] ERROR\n%s", ts, trace)
  -- Could log to file here
  io.stderr:write(report .. "\n")
  return report
end

local ok, msg = xpcall(
  function()
    local t = nil
    return t.field   -- error!
  end,
  errorHandler
)
print("ok:", ok)

Hanteraren får inte ge fel

Om meddelandehanteraren själv ger ett fel returnerar Lua en felindikator utan att anropa hanteraren igen. Skriv alltid hanterare som är robusta — använd ingen I/O som kan misslyckas och ingen indexering av nil.

local function safeHandler(err)
  -- Keep handler simple and safe
  local ok, trace = pcall(debug.traceback, err, 2)
  if ok then return trace
  else return tostring(err) .. " (traceback failed)"
  end
end

local ok, msg = xpcall(
  function() error({complex="error table"}) end,
  safeHandler
)
print(ok, type(msg))

xpcall för huvudloopen

I långvariga program (servrar, spell loopar) kan ni omsluta huvudfunktionen med xpcall för att fånga och logga fel som annars skulle förbli ohanterade, utan att programmet kraschar. Huvudloopen kan sedan avgöra om den ska startas om eller avslutas.

local function mainApp()
  -- simulate work
  for i = 1, 3 do
    print("Tick", i)
    if i == 2 then error("transient error") end
  end
end

local function handler(e)
  return debug.traceback("App error: "..tostring(e), 2)
end

local ok, err = xpcall(mainApp, handler)
if not ok then
  print("Application crashed:\n" .. err)
end

Strukturerad felrapportering

Kombinera xpcall med strukturerade felobjekt och en omfattande hanterare för att skapa detaljerade och användbara felrapporter för felsökning eller övervakningspaneler.

local function handler(err)
  local info = {
    error   = tostring(err),
    time    = os.date("!%Y-%m-%dT%H:%M:%SZ"),
    trace   = debug.traceback(nil, 2),
  }
  return info
end

local ok, report = xpcall(
  function() error({code=500, msg="internal error"}) end,
  handler
)

if not ok then
  print("Time:", report.time)
  print("Error:", report.error)
  -- print("Trace:", report.trace)
end

xpcall för coroutines

Inuti en coroutine fungerar pcall normalt. Om ni vill få stackspårningar från fel inuti coroutines omsluter ni coroutine-kroppen med xpcall. Hanteraren körs i coroutine-stackens sammanhang.

local function co_body()
  error("error inside coroutine")
end

local co = coroutine.create(function()
  local ok, err = xpcall(co_body, debug.traceback)
  if not ok then
    print("Caught in coroutine:", err:match("([^\n]+)"))
  end
end)

coroutine.resume(co)

Utökning av felobjekt

Hanteraren kan omvandla ett enkelt strängfel till ett omfattande objekt eller bygga ut ett redan omfattande objekt ytterligare. På så sätt kan kod på lägre nivå kasta enkla fel medan hanteraren lägger till sammanhang (begärande-ID, användarsession, miljöinformation).

local requestID = "req-123"

local function handler(err)
  if type(err) == "string" then
    return {message=err, requestID=requestID, level="error"}
  end
  err.requestID = requestID
  return err
end

local ok, result = xpcall(
  function() error("database timeout") end,
  handler
)

if not ok then
  print(result.message, result.requestID)
  -- database timeout  req-123
end

Jämförelse mellan pcall och xpcall

Använd pcall när: ni bara behöver felvärdet, felet förväntas och hanteras direkt, eller enkelhet är viktigt. Använd xpcall när: ni behöver stackspårningar, befinner er vid en toppnivågräns eller vill lägga till sammanhang i alla fel.

-- pcall: simple, no overhead
local ok, err = pcall(function()
  return 1/0   -- no error in Lua! returns inf
end)
print(ok, err)   -- true  inf

-- xpcall: adds traceback
local ok2, err2 = xpcall(
  function() error("real error") end,
  debug.traceback
)
print(ok2)       -- false
print(err2:sub(1,40))  -- first line of traceback

Hanterarens returvärde

Vad hanteraren än returnerar blir xpcalls andra värde. Om hanteraren returnerar nil blir xpcalls andra returvärde nil. En hanterare som returnerar det ursprungliga felobjektet tillsammans med extra information är det mest flexibla alternativet.

local function enrichedHandler(err)
  return {
    original = err,
    traceback = debug.traceback(nil, 2),
    timestamp = os.time(),
  }
end

local ok, report = xpcall(
  function() error("oops") end,
  enrichedHandler
)

if not ok then
  print(type(report))          -- table
  print(report.original)       -- ...: oops
  print(report.timestamp > 0)  -- true
end

Snabbkontroll

Vilken är den viktigaste fördelen med xpcall jämfört med pcall?

Sammanfattning: xpcall

Sammanfattning:

  • xpcall(f, handler, ...) — hanteraren körs medan stacken är intakt
  • Använd debug.traceback som hanterare för fullständiga stackspårningar
  • Hanteraren får inte ge fel — håll den enkel
  • Berika fel med sammanhang i hanteraren
  • Omslut huvudloopar och serverhanterare med xpcall
  • Hanterarens returvärde blir xpcalls andra returvärde
Gratis att börja

Lär dig Lua med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
40
Lektioner
159

Vanliga frågor

Är lektionen ”xpcall och meddelandehanterare” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Lua Academy, inklusive ”xpcall och meddelandehanterare”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Lua Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”xpcall och meddelandehanterare”?

Använd xpcall med en anpassad hanterare för detaljerade felspårningar. Ni övar på Lua Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Lua Academy?

Du behöver inga förkunskaper. Utbildningen i Lua Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 4.

Hur lång tid tar lektionen ”xpcall och meddelandehanterare”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Lua Academy-lektionen?

Ja. Varje Lua Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Funktionen error()
  2. Skyddade anrop med pcall
  3. xpcall och meddelandehanterare
  4. Strukturerade felobjekt
← Tillbaka till Lua Academy