ترکیب Express و Typescript: درخواست‌هایGET و PATCH

Combining Typescript and Express: GET and PATCH Requests

01 شهریور 1399
ترکیب Express و Typescript: درخواست هایGET و  PATCH– قسمت 78

در قسمت قبل اولین درخواست POST خود را کدنویسی کردیم اما هنوز route های دیگری را نیز داریم. برای تکمیل این route ها نیز به فایل todos.ts در پوشه controller می رویم و ابتدا متدی برای get تعریف می کنیم:

export const createTodo: RequestHandler = (req, res, next) => {
  const text = (req.body as { text: string }).text;
  const newTodo = new Todo(Math.random().toString(), text);

  TODOS.push(newTodo);

  res.status(201).json({ message: 'Created the todo.', createdTodo: newTodo });
};

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

متد createTodo را در جلسه قبل تکمیل کردیم که برای درخواست های POST ساختن یک todo جدید بود. ما از پایگاه داده در برنامه خودمان استفاده نمی کنیم و مقادیر جدید را درون یک آرایه ساده می گذاریم بنابراین با هر بار تغییر کدها و ریستارت شدن سرور همه چیز پاک می شود (اگر قسمت قبل را مطالعه نکرده اید حتما به آن برگردید).

همانطور که می بینید در ابتدا تایپ این تابع را از نوع RequestHandler قرار داده ام تا مجبور به تعیین تایپ برای تک تک پارامترها نشویم. تنها کاری که این تابع انجام می دهد برگرداندن یک شیء است که حاوی آرایه TODOS باشد. البته یادتان باشد که با هر بار تغییر کد، آرایه TODOS  خالی می شود.

حالا به todos.ts در پوشه routes می رویم و این تابع را در آن وارد می کنیم:

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

سپس می توانیم از آن استفاده کنیم:

const router = Router();

router.post('/', createTodo);

router.get('/', getTodos);

// بقیه کدها //

برای تست کردن کدها می توانیم برنامه postman را باز کرده و آدرس http://localhost:3000/todos/ یک درخواست Get خالی ارسال کنیم. منظورم از درخواست خالی این است که هیچ نوع body برای آن تعیین نکنید و پس از تعیین URL و قرارگیری نوع درخواست روی GET فقط دکمه send را بزنید. با این کار یک آرایه خالی دریافت خواهیم کرد. چرا خالی؟ به دلیل اینکه در حالت پیش فرض چیزی درون این آرایه وجود ندارد. شما می توانید یک درخواست post جدید ایجاد کرده (مانند آنچه که در جلسه قبل توضیح داده شد) و سپس دوباره درخواست GET خود را ارسال نمایید. با این کار به جای دریافت یک آرایه خالی، یک آرایه با مقدار ثبت شده در درخواست POST قبلی را مشاهده می کنید.

تنها چیزی که باقی می ماند متد های patch و delete هستند بنابراین من از patch شروع می کنم. وارد فایل todo.ts در پوشه controller شده و تابع زیر را در آن تعریف کنید:

export const updateTodo: RequestHandler = (req, res, next) => {

}

همانطور که می بینید این تایپ این تابع RequestHandler است. اگر یادتان باشد متد patch همیشه یک id را به همراه خود ارسال می کند بنابراین می توان گفت:

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

}

همانطور که می دانید با استفاده از req.params می توانیم به پارامترهای یک درخواست دسترسی داشته باشیم و سپس به کلید id دسترسی پیدا کرده ایم. این آیدی در متغیر todoId ذخیره می شود اما هیچ نوعی type support ای را برای آن نمی گیریم چرا که تایپ اسکریپت نمی داند id پاس داده شده از نوع رشته خواهد بود. از طرفی ما می دانیم که RequestHandler یک generic type است و می توانیم آن را دقیق تر کرده و پارامترهای دریافتی خود را مشخص کنیم:

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

}

حالا تایپ اسکریپت متوجه کد ما خواهد شد و می داند که یک id از نوع رشته را خواهیم داشت. در مرحله بعد باید متن جدید را دریافت کنیم (درخواست patch یا به روز رسانی، نیاز به مقداری جدیدی دارد که به جای مقدار قدیمی قرار دهد) بنابراین می گوییم:

    const todoId = req.params.id;

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

من می دانم که متن جدید در body درخواست من وجود دارد اما برای اینکه به تایپ اسکریپت نیز اعلام کنم، از type casting استفاده کرده ام؛ یعنی با استفاده از کلیدواژه as به آن گفته ام که در body من خصوصیتی به نام text خواهیم داشت که از نوع رشته ای است. حالا برای به روز رسانی آرایه TODOS نیاز به داشتن index آیتم مورد نظرمان داریم بنابراین:

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 روی تک تک اعضای آرایه TODOS اجرا می شود و index اولین عنصری را که با شرط پاس داده شده به آن تطابق داشته باشد، به ما برمی گرداند. در غیر این صورت مقدار 1- برگردانده خواهد شد. مثال:

const array1 = [5, 12, 8, 130, 44];

const isLargeNumber = (element) => element > 13;

console.log(array1.findIndex(isLargeNumber));

خروجی کد بالا عدد 3 است چرا که اولین مقدار بزرگتر از 13 آیتم چهارم (ایندکس سوم) می باشد.

من در تابع updateTodo گفته ام اگر todo.id با todoId (آیدی پاس داده شده در درخواست) یکی باشد یعنی عنصر خود را پیدا کرده ایم. حالا ممکن است به هر دلیلی todo خود را پیدا نکرده باشیم. در این صورت چه کاری می توان انجام داد؟ از آنجایی که در برنامه API ما مقدار id از طرف کاربر ارسال می شود، ممکن است id کاملا اشتباهی ارسال شود و چنین id وجود نداشته باشد؟ دوست دارم که خودتان فکر کرده و راه حل را پیدا کنید (راه های مختلفی برای آن وجود دارد و تنها یک راه درست نیست). در قسمت بعد در مورد این موضوع بیشتر صحبت خواهیم کرد.

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

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

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