الاستدعاءات المحمية باستخدام pcall
التقط الأخطاء بأمان باستخدام pcall وفسّر القيم المرجعة
الاستدعاءات المحمية باستخدام pcall درس مجاني في Lua Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Lua Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Lua Academy 4 دروس في المجموع.
أساسيات pcall
يستدعي pcall(f, ...) الدالة f بالوسائط ... في وضع محمي. إذا نجحت f، يعيد pcall القيمة true متبوعةً بجميع قيم الإرجاع. وإذا أصدرت f خطأً، يعيد pcall القيمة false متبوعةً برسالة الخطأ. يستمر البرنامج في كلتا الحالتين.
local function risky(x)
if x < 0 then error("negative input: " .. x) end
return math.sqrt(x)
end
local ok, result = pcall(risky, 9)
print(ok, result) -- true 3.0
ok, result = pcall(risky, -1)
print(ok, result) -- false ...: negative input: -1التقاط أخطاء محددة
تحقق من نوع قيمة الخطأ بعد pcall لمعالجة أنواع الأخطاء المختلفة بطرق مختلفة. تحتوي أخطاء الجداول على بيانات منظّمة، بينما تحتوي الأخطاء النصية على رسالة. احرص دائمًا على معالجة كلتا الحالتين.
local function op(errType)
if errType == "table" then
error({code=42, msg="structured error"})
else
error("plain string error")
end
end
local ok, err = pcall(op, "table")
if not ok then
if type(err) == "table" then
print("Code:", err.code, "Msg:", err.msg)
else
print("String error:", err)
end
endقيم إرجاع متعددة عند النجاح
عند النجاح، يعيد pcall جميع قيم الإرجاع الخاصة بالدالة المحمية بعد القيمة true الأولية. التقط هذه القيم باستخدام متغيرات متعددة.
local function compute(a, b)
return a + b, a * b, a - b
end
local ok, sum, product, diff = pcall(compute, 6, 4)
if ok then
print("sum:", sum, "product:", product, "diff:", diff)
-- sum: 10 product: 24 diff: 2
endتداخل pcall
يمكن تداخل استدعاءات pcall. ينشئ كل pcall نطاقًا محميًا مستقلًا. يلتقط pcall الداخلي الخطأ الواقع داخله، وليس pcall الخارجي. يتيح لك ذلك تنفيذ استراتيجيات بديلة.
local function tryPrimary()
error("primary failed")
end
local function tryFallback()
return "fallback result"
end
local ok, result = pcall(tryPrimary)
if not ok then
print("Primary failed:", result)
ok, result = pcall(tryFallback)
end
if ok then print("Got:", result) end -- fallback resultاستخدام pcall مع الأساليب
لاستدعاء أسلوب (باستخدام صيغة النقطتين) عبر pcall، مرّر الدالة والكائن بوصفهما الوسيطين الأولين. pcall(obj.method, obj, args...) أو غلّف الاستدعاء في إغلاق.
local obj = {
x = 10,
compute = function(self, n)
if n == 0 then error("zero divisor") end
return self.x / n
end
}
-- Pass method + self explicitly
local ok, v = pcall(obj.compute, obj, 2)
print(ok, v) -- true 5.0
-- Or use a closure
ok, v = pcall(function() return obj:compute(0) end)
print(ok, v) -- false ...zero divisorاستخدام pcall لأمان عمليات الإدخال والإخراج
غلّف عمليات الإدخال والإخراج في pcall لالتقاط أخطاء نظام التشغيل غير المتوقعة. أعد زوجًا متسقًا من النتيجة والخطأ حتى يتمكن المستدعون من معالجة حالات الفشل بسلاسة.
local function safeRead(path)
local ok, result = pcall(function()
local f = assert(io.open(path, "r"))
local content = f:read("a")
f:close()
return content
end)
if ok then return result
else return nil, result
end
end
local data, err = safeRead("config.txt")
if data then print("Read", #data, "bytes")
else print("Error:", err)
endنمط إعادة المحاولة باستخدام pcall
أعد محاولة عملية غير مستقرة (مثل طلب شبكة أو كتابة ملف) حتى N مرات، باستخدام pcall لالتقاط الأخطاء. أضف فترة انتظار بين المحاولات في الشيفرة الفعلية (أو استخدم coroutines).
local function retry(fn, maxAttempts)
local attempts = 0
while attempts < maxAttempts do
attempts = attempts + 1
local ok, result = pcall(fn)
if ok then
print("Succeeded on attempt", attempts)
return result
end
print("Attempt", attempts, "failed:", result)
end
error("all " .. maxAttempts .. " attempts failed")
end
local n = 0
retry(function()
n = n + 1
if n < 3 then error("not ready") end
return "done"
end, 5)تخزين نتائج pcall في جدول
عند استخدام pcall داخل حلقة، خزّن النتائج في جدول لتحليلها لاحقًا. يفيد ذلك في العمليات الدفعية التي تريد فيها معالجة جميع العناصر وجمع الأخطاء بدلًا من التوقف عند أول فشل.
local jobs = {10, -5, 25, 0, 16}
local results = {}
for _, n in ipairs(jobs) do
local ok, v = pcall(function()
if n < 0 then error("negative") end
return math.sqrt(n)
end)
results[#results+1] = {input=n, ok=ok, value=v}
end
for _, r in ipairs(results) do
if r.ok then
print(r.input, "->", string.format("%.3f", r.value))
else
print(r.input, "-> ERROR:", r.value)
end
endpcall مقارنةً بـ xpcall
يلتقط pcall الخطأ، لكنه يمنحك قيمة الخطأ فقط. يتيح لك xpcall توفير دالة لمعالجة الرسالة تعمل بينما يكون المكدس سليمًا، مما يتيح إنشاء تتبعات للمكدس. اختر xpcall عندما تحتاج إلى تتبعات الأخطاء.
-- pcall: simple, no traceback
local ok1, err1 = pcall(function()
error("simple error")
end)
print(err1) -- only the error message
-- xpcall: with traceback handler
local ok2, err2 = xpcall(
function() error("traced error") end,
function(e) return debug.traceback(e, 2) end
)
print(err2) -- full stack traceاتفاقية إرجاع pcall
استخدم pcall أساسًا لواجهة برمجية متسقة: أعد دائمًا value عند النجاح، أو nil, errorMessage عند الفشل. ابنِ دوالك على هذا النحو حتى يعرف المستدعون دائمًا ما يمكن توقعه.
local function loadJSON(path)
local ok, result = pcall(function()
local f = assert(io.open(path, "r"))
local text = f:read("a")
f:close()
-- Fake JSON parse for demo
return {data = text, path = path}
end)
if ok then return result
else return nil, result
end
end
local data, err = loadJSON("data.json")
if data then print("Loaded:", data.path)
else print("Failed:", err)
endتحقق سريع
ماذا يعيد pcall عندما تنجح الدالة المحمية؟
مراجعة: pcall
الملخص:
pcall(f, ...)→true, results...أوfalse, err- تحقق من قيمة الإرجاع الأولى لتحديد النجاح أو الفشل
- تأتي قيم الإرجاع المتعددة بعد true عند النجاح
- pcall المتداخل: يلتقط كل استدعاء أخطاءه باستقلالية
- نمط إعادة المحاولة: استخدم حلقة مع pcall للعمليات غير المستقرة
- استخدم xpcall عندما تحتاج إلى تتبعات المكدس
الأسئلة الشائعة
هل درس «الاستدعاءات المحمية باستخدام pcall» مجاني؟
نعم — نص درس «الاستدعاءات المحمية باستخدام pcall» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Lua Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Lua Academy 4 دروس في المجموع.
ماذا ستتعلم في «الاستدعاءات المحمية باستخدام pcall»؟
التقط الأخطاء بأمان باستخدام pcall وفسّر القيم المرجعة تتمرن على Lua Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Lua Academy؟
لا تُشترط خبرة سابقة. Lua Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «الاستدعاءات المحمية باستخدام pcall»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Lua Academy هذا؟
نعم. كل درس في Lua Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- الدالة error()
- الاستدعاءات المحمية باستخدام pcall
- xpcall ومعالجات الرسائل
- كائنات الأخطاء المهيكلة