Kodokon kodokon.com

اللاتزامن في الممارسة العملية

استخدم async/await في مساراتك، وتعامل مع الأخطاء اللاتزامنية دون إسقاط الخادم.

10 دقيقة · 3 أسئلة

افتح هذا الدرس في Kodokon

لا تُرجِع مساراتك الحقيقية مصفوفات في الذاكرة: بل تقرأ الملفات، وتستعلم من قاعدة بيانات، وتستدعي واجهات برمجية أخرى. وكل هذه العمليات لاتزامنية. أنت تعرف async/await منذ مسار JavaScript؛ لنرَ كيفية استخدامها بنظافة في خادم. أول خبر سار: يمكن لدالة المسار أن تكون async.

JAVASCRIPT
import express from "express";
import { readFile } from "node:fs/promises";

const app = express();

app.get("/report", async (req, res) => {
  const raw = await readFile("report.json", "utf8");
  res.json(JSON.parse(raw));
});

app.listen(3000);

يعمل هذا الكود... ما دام report.json موجودًا. فإذا فشلت القراءة، يُرفَض الوعد، وبحسب إصدار Express، يبقى الطلب دون رد أو يتسرب الخطأ إلى السجلات. والقاعدة المهنية: كل مسار لاتزامني يتعامل مع أخطائه، باستخدام try/catch وnext(error).

JAVASCRIPT
app.get("/report", async (req, res, next) => {
  try {
    const raw = await readFile("report.json", "utf8");
    res.json(JSON.parse(raw));
  } catch (error) {
    next(error);
  }
});

تمرِّر next(error) الخطأ إلى معالِج الأخطاء المركزي. وهو برمجية وسيطة ذات أربعة وسائط، مُصرَّح بها بعد كل المسارات. مكان واحد لتسجيل الأخطاء وتنسيقها: هذا ما يميّز واجهة برمجية قابلة للصيانة عن مشروع عطلة نهاية أسبوع.

JAVASCRIPT
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({
    error: "Internal server error"
  });
});
دائمًا في الأخير، بعد المسارات

عادة أخيرة يجب اكتسابها: التوازي. عمليتان مستقلتان مربوطتان بـ await مرتين تُنفَّذان الواحدة تلو الأخرى. أما Promise.all فتطلقهما معًا: فيكون زمن الرد هو زمن الأبطأ، لا مجموع الاثنين.

JAVASCRIPT
async function fetchUsers() {
  return [{ id: 1, name: "Ada" }];
}

async function fetchTasks() {
  return [{ id: 1, title: "Review the code" }];
}

app.get("/dashboard", async (req, res, next) => {
  try {
    const [users, tasks] = await Promise.all([
      fetchUsers(),
      fetchTasks()
    ]);
    res.json({ users, tasks });
  } catch (error) {
    next(error);
  }
});

اختبار المعرفة

تأكّد من أنك تذكّرت النقاط الأساسية في هذا الدرس.

  1. في مسار async، ماذا تفعل بخطأ التقطته catch؟
    • تسجيله باستخدام console.log والمتابعة
    • استدعاء next(error) لتمريره إلى معالِج الأخطاء
    • إعادة محاولة الطلب تلقائيًا
  2. يجب تنفيذ استدعاءين لاتزامنيين مستقلين بأسرع ما يمكن. أيّ أسلوب تختار؟
    • ربطهما بـ await متتاليين
    • إطلاقهما معًا باستخدام Promise.all
    • استخدام setTimeout بينهما
  3. كيف يتعرّف Express على برمجية وسيطة لمعالجة الأخطاء؟
    • من خلال توقيعها ذي الوسائط الأربعة، مع err أولًا
    • من خلال اسم الدالة، الذي يجب أن يكون errorHandler
    • من خلال موضعها في أعلى الملف