ترکیب Express و Typescript: دیگر عملیات‌های CRUD

Combining Typescript and Express: Other CRUD Operations

01 شهریور 1399
ترکیب Express و Typescript: دیگر عملیات های CRUD – قسمت پایانی (79)

در قسمت قبل درخواست ساده GET خود را تکمیل کردیم:

export const getTodos: RequestHandler = (req, res, next) => {
  res.json({ todos: TODOS });
};

اما در هنگام کدنویسی درخواست PATCH به مشکل برخوردیم:

export const updateTodo: RequestHandler<{ id: string }> = (req, res, next) => {
    const todoId = req.params.id;

    const updatedText = (req.body as { text: string }).text;

    const todoIndex = TODOS.findIndex(todo => todo.id === todoId);
}

ما با استفاده از تابع findIndex باید index آیتم مورد نظر برای ویرایش را پیدا می کردیم و همین کار را نیز انجام داده ایم اما اگر کاربر id اشتباهی را به برنامه ما پاس بدهد همه چیز خراب می شود. برای حل این مشکل می توانیم به شکل زیر عمل کنیم:

export const updateTodo: RequestHandler<{ id: string }> = (req, res, next) => {
    const todoId = req.params.id;

    const updatedText = (req.body as { text: string }).text;

    const todoIndex = TODOS.findIndex(todo => todo.id === todoId);

    if (todoIndex < 0) {
        throw new Error('Could not find todo!');
    }
}

همانطور که در جلسه قبل توضیح دادم، اگر findIndex مقدار index پاس داده شده را پیدا نکند، عدد 1- را برمی گرداند. من از این موضوع استفاده می کنم و می گویم اگر todoIndex از صفر کوچک تر بود یک Error جدید پرتاب شود که می گوید چنین todo ای وجود ندارد (Could not find todo!). پرتاب این خطا، باعث می شود که کد زیر در فایل app.ts فعال شود:

app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  res.status(500).json({ message: err.message });
});

اگر یادتان باشد این کد را نوشته بودیم تا مسئول مدیریت خطاهای ما باشد و شیء json ای را با پیام خطای ما به کاربر ارسال کند. از طرفی می دانیم که با پرتاب شدن Error در زبان جاوا اسکریپت، قسمت های بعدی کد اجرا نمی شوند بنابراین می توانیم ادامه کدهای خود را به راحتی بنویسیم چرا که اگر شرط if خطایی پیدا کند کدهای بعد از آن اجرا نخواهند شد.

در مرحله بعد به راحتی می توانیم آرایه TODOS را به روز رسانی کنیم:

export const updateTodo: RequestHandler<{ id: string }> = (req, res, next) => {
    const todoId = req.params.id;

    const updatedText = (req.body as { text: string }).text;

    const todoIndex = TODOS.findIndex(todo => todo.id === todoId);

    if (todoIndex < 0) {
        throw new Error('Could not find todo!');
    }

    TODOS[todoIndex] = new Todo(TODOS[todoIndex].id, updatedText);
}

من از todoIndex استفاده کرده ام تا به عنصر مورد نظر در آرایه TODOS دسترسی داشته باشیم. سپس با استفاده از کلاس Todo یک todo جدید ساخته ایم. من می خواهم id این todo تغییر نکند بنابراین به شکل بالا به همان id قبلی دسترسی پیدا کرده ام. در یک برنامه API هر مقداری یک id دارد و این id مشخص کننده ماهیت آن مقدار است و با به روز رسانی یک مقدار، نباید ماهیت آن تغییر کند بلکه فقط مقدار آن عوض می شود. دلیل تغییر ندادن id این بود. برای متن جدید نیز از متغیر updatedText استفاده کرده ایم.

در نهایت برای اینکه کاربر بفهمد چه اتفاقی افتاده است و آیا آیتم مورد نظر به روز رسانی شده است از res استفاده می کنیم تا یک پاسخ را به سمت کاربر ارسال کنیم:

export const updateTodo: RequestHandler<{ id: string }> = (req, res, next) => {
    const todoId = req.params.id;
  
    const updatedText = (req.body as { text: string }).text;
  
    const todoIndex = TODOS.findIndex(todo => todo.id === todoId);
  
    if (todoIndex < 0) {
      throw new Error('Could not find todo!');
    }
  
    TODOS[todoIndex] = new Todo(TODOS[todoIndex].id, updatedText);
  
    res.json({ message: 'Updated!', updatedTodo: TODOS[todoIndex] });
  };

پاسخ من یک شیء json است که message آن برابر updated (به معنی «به روز رسانی شد») می باشد. همچنین Todo جدید را نیز برمی گردانیم تا کاربر دقیقا ببیند چه چیزی تغییر کرده است.

حالا به فایل todo.ts درون پوشه routes بروید و این تابع را به درخواست PATCH متصل کنید:

import { createTodo, getTodos, updateTodo } from '../controllers/todos';

const router = Router();

router.post('/', createTodo);

router.get('/', getTodos);

router.patch('/:id', updateTodo);
// بقیه کدها //

حالا برای تست کردن برنامه به postman می رویم و نوع درخواست خود را PATCH می گذاریم. سپس URL را مثل همیشه روی http://localhost:3000/todos/ می گذاریم اما باید در انتهای آن id مورد نظر را نیز اضافه کنیم. از آنجایی که سرور ما ریستارت شده است (کدها را تغییر داده ایم) هیچ todo ای برای ویرایش و تست نداریم بنابراین ابتدا یک درخواست POST (مطابق آنچه دو جلسه قبل توضیح دادم) ارسال کنید تا tood ای داشته باشیم. سپس id آن را برداشته و آن را به انتهای URL برای درخواست PATCH بچسبانیم. مثلا:

http://localhost:3000/todos/0.26396258475215982

قبل از کلیک روی send باید به سربرگ body رفته و آن را روی raw و json تنظیم کنید. اگر یادتان باشد برنامه ما به دنبال text در بدنه درخواست های ارسالی می گردد بنابراین چیزی شبیه به ساختار زیر را برای body بنویسید:

{
    "text": "finish the course"
}
ارسال دستور patch با استفاده از postman
ارسال دستور patch با استفاده از postman

اگر id را به اشتباه ارسال کنید با پیام Todo not found روبرو می شوید. حالا اگر درخواست GET را دوباره اجرا کنید، می بینید که تعداد todo ها هنوز هم یکی است اما مقدار آن تغییر کرده است.

در نهایت متد خود را برای درخواست های Delete می نویسم (فایل todo.ts در پوشه Controller):

export const deleteTodo: RequestHandler = (req, res, next) => {
  const todoId = req.params.id;

  const todoIndex = TODOS.findIndex(todo => todo.id === todoId);

  if (todoIndex < 0) {
    throw new Error('Could not find todo!');
  }

  TODOS.splice(todoIndex, 1);

  res.json({ message: 'Todo deleted!' });
};

من در اینجا همان کد قبلی را کپی کرده ام و پس از مشخص کردن index با استفاده از متد splice آن آیتم را از آرایه TODOS حذف کرده ام. نهایتا res (پاسخ) خود را نیز دریافت کرده ام. حالا به todo.ts در پوشه routes می رویم تا آن را به متد خود متصل کنیم:

import { Router } from 'express';

import { createTodo, getTodos, updateTodo, deleteTodo } from '../controllers/todos';

const router = Router();

router.post('/', createTodo);

router.get('/', getTodos);

router.patch('/:id', updateTodo);

router.delete('/:id', deleteTodo);

export default router;

می توانید این برنامه را با postman تست کنید.

با پایان این قسمت، دوره آموزشی تایپ اسکریپت به طور کامل به پایان می رسد. امیدوارم به خوبی با typescript آشنا شده باشید. ما تمام مباحث تایپ اسکریپت را بررسی کردیم و شما با 100 درصد آن آشنا شده اید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش جامع تایپ اسکریپت توصیه می‌کند:
نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

ما را دنبال کنید
اینستاگرام روکسو تلگرام روکسو ایمیل و خبرنامه روکسو