برنامه نویسی

تجزیه اثر TS: قسمت 2

در مقاله قبلی ، ما Effect-TS را معرفی کردیم ، کتابخانه ای که برای مقابله با چالش های متداول در توسعه برنامه ها ، مانند رسیدگی به عوارض جانبی پیچیده ، مدیریت همزمانی و رسیدگی به خطا ، طراحی شده است. Effect-TS برای توسعه دهندگان که به دنبال برنامه های قوی با تمرکز بر قوام ، ایمنی از نوع و همزمانی پیشرفته هستند ، ایده آل است. ما به طور خلاصه در مورد اصول تأثیرات ، از جمله نوع آنها و نحوه ایجاد و اجرای آنها بحث کردیم.

در این پست ، ما عمیق تر به ایجاد و اجرای اثرات می پردازیم و نمونه ای از اعتماد به نفس خود را در استفاده از اثربخشی TS ارائه می دهیم.

بر خلاف توابع استاندارد TypeScript ، اثرات موجود در اثر TS نه ذاتاً همزمان است و نه ناهمزمان. آنها به سادگی محاسباتی را توصیف می کنند که می توانند موفق شوند یا منجر به خطا شوند.

بیایید ابتدا با

Effects with Synchronous computations:

محاسبات همزمان به صورت متوالی انجام می شود و اجرای بیشتر را تا زمان تکمیل ، مسدود می کند و نتایج فوری و قطعی تولید می کند.
در اثر TS ، می توانید محاسبات همزمان را با استفاده از Effect.syncبشر

const generateRandomNumber = Effect.sync(() => Math.random());
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

Effect.sync همیشه یک مقدار موفقیت را برمی گرداندبشر اگر خطایی را به وجود آورد ، این نشانگر نقص است نه یک خرابی اثر معمولی. بنابراین ، استفاده کنید Effect.Sync فقط وقتی مطمئن باشید که عملکرد شما شکست نخواهد خورد

اجرای GeneraterAndomNumber به طور مستقیم نتیجه مطلوب را به همراه نخواهد داشت ، زیرا اثرات آن تنبل و تعویق است تا زمان لازم باشد. برای اجرای اثر و به دست آوردن نتیجه محاسبات ، استفاده کنید:

Effect.runSync(generateRandomNumber)
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

با این کار ، اثر همگام سازی بلافاصله اجرا می شود.

وقتی می دانید که عملکرد شما ممکن است شکست بخورد ، از آن استفاده کنید Effect.tryبشر این ساختار به شما امکان می دهد استثنائات را به صورت عملکردی کنترل کنید:

const parseJson = (jsonString: string): Effect.Effect<unknown, Error, unknown> =>
  Effect.try({
    try: () => JSON.parse(jsonString),
    catch: (error) => new Error(`Failed to parse JSON: ${(error as Error).message}`),
  });
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

برای اجرای این اثر ، آن را با آن اجرا کنید Effect.runSync:

const inputString ='{"name": "Alice", "age": 30}';
try {
Effect.runSync(parseJson(inputString)); 
} catch (error) {
  console.error(error);
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

این اثر همزمان را اجرا می کند ، هرگونه خطای تجزیه را صید و وارد می کند.

Effects with Asynchronous computations:

محاسبات ناهمزمان شامل کارهایی است که به طور مستقل از جریان اصلی برنامه اجرا می شود و به سایر عملیات اجازه می دهد در حالی که منتظر نتیجه هستند ، ادامه یابد.

در اثر TS ، محاسبات ناهمزمان با استفاده از Effect.tryPromise عملکرد. این عملکرد یک عمل ناهمزمان مانند یک وعده را به یک اثر می رساند و به شما امکان می دهد فرآیندهای ناهمزمان را به صورت کاربردی و ایمن از نوع استفاده کنید.

const fetchData = (url: string): Effect.Effect<unknown, Error, Response> =>
  Effect.tryPromise({
    try: () => fetch(url), 
    catch: (error) => new Error(`Failed to fetch data: ${(error as Error).message}`),
  });
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

برای اجرای یک اثر ناهمزمان ، استفاده می کنید Effect.runPromise، که ماهیت مبتنی بر عمل عملیات را کنترل می کند:

const url = "https://api.example.com/data";
Effect.runPromise(fetchData(url))
  .then(data => console.log(data))
  .catch(error => console.error(error));
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

Avoid Executing Effects Within Other Effects:

همیشه هدف خود را برای اجرای جلوه ها در مرزهای برنامه خود ، مانند عملکردهای اصلی انجام دهید. اجرای اثرات در سایر جلوه ها ، مزایای استفاده از یک سیستم اثر را نفی می کند ، زیرا جدایی روشن بین توضیحات اثر و اجرای را محو می کند. با حفظ این جدایی ، اطمینان حاصل می کنید که برنامه شما مدولار ، قابل پیش بینی و آزمایش و نگهداری آسان تر است.

Combinators: Combining, Transforming, and Managing Effects

ترکیبات چارچوبی را برای ایجاد توضیحات جلوه ای بیانگر و مدولار بدون اجرای آنها فراهم می کنند. با جلوگیری از لانه سازی اثرات و استفاده از ترکیبات در عوض ، شما از قدرت کامل سیستم های اثر استفاده می کنید ، و با اصول برنامه نویسی عملکردی هماهنگ می شوید.

به جای اجرای اثرات در سایر جلوه ها:

const initialEffect = Effect.succeed(4);
const transformedEffect = Effect.sync(() => {
  const result = Effect.runSync(initialEffect);
  return result * 2;
});
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

شما می توانید از ترکیبات برای حفظ جدایی برای EG استفاده کنید

Effect.map: این اثر می گذارد و به شما امکان می دهد نتیجه ای را که با استفاده از یک عملکرد ساده تولید می کند تغییر دهید.

const initialEffect = Effect.succeed(4);
const transformedEffect = Effect.map(initialEffect, x => x * 2);

حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

این تحول اثر را اجرا نمی کند. این تنها نتیجه را پس از اجرای اثر اصلاح می کند.

Effect.flatMap: خروجی یک اثر ، که اثر دیگری ایجاد می کند ، می گیرد و نتیجه را صاف می کند. این معمولاً در صورت نیاز به انجام محاسبات متوالی که منجر به اثر می شوند ، استفاده می شود و این امکان را می دهد تا محاسبه بعدی به مقدار تولید شده توسط اولین اثر بستگی داشته باشد.

const initialEffect = Effect.succeed(10);
const chainedEffect = Effect.flatMap(initialEffect, x => Effect.succeed(x * 2));
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

pipe: این امکان را به توابع زنجیره ای به صورت چپ به راست می دهد و باعث افزایش خوانایی می شود

const pipeline = pipe(
  Effect.succeed(10),
  Effect.map(x => x + 5),
  Effect.map(x => x * 2)
);
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

و بسیاری موارد دیگر برای کمک به شما در رسیدگی سناریوهای مختلف به طور مؤثر وجود دارد ….

بیایید برنامه ای به نام DataTransformer بسازیم تا داده ها را از یک سطل S3 بارگیری کنیم ، آن را تغییر دهیم و سپس دوباره آن را به S3 بارگذاری کنیم. این مثال درک عملی از اثربخشی Ts در عمل را ارائه می دهد.

ابتدا یک مشتری S3 ایجاد می کنیم و کارکردهای مورد نیاز برای وظایف خود را تعریف می کنیم:

import { S3Client, GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3";
import { Effect, pipe } from 'effect';

const s3Client = 
  new S3Client({
    region: "your-region",
    forcePathStyle: true,
  });

const downloadData = (bucket: string, key: string): Effect.Effect<string, Error> =>
  Effect.tryPromise({
    try: async () => {
      const response = await s3Client.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
      return response.Body?.transformToString() ?? "";
    },
    catch: (error) => new Error(`Failed to download data: ${error.message}`),
  });


const transformData = (data: string) =>
  Effect.sync(() => {
    return data.toUpperCase();
  });


const uploadData = (bucket: string, key: string, data: string) =>
  Effect.tryPromise({
    try: () =>
      s3Client.send(
        new PutObjectCommand({
          Bucket: bucket,
          Key: key,
          Body: data,
        })
      ),
    catch: (error) => new Error(`Failed to upload data: ${error.message}`),
  });

حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

در مرحله بعد ، ما عملکرد ترانسفورماتور را با استفاده از ترکیبات مؤثر TS تشکیل می دهیم:

const dataTransformer = (sourceBucket: string, sourceKey: string, targetBucket: string, targetKey: string) =>
  pipe(
    downloadData(sourceBucket, sourceKey),
    Effect.flatMap(transformData),
    Effect.andThen((transformedData) => uploadData(targetBucket, targetKey, transformedData))
  );
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

سرانجام ، ما عملکرد اصلی را برای اجرای محاسبات اثرات تعریف می کنیم:

Effect.runPromise(dataTransformer("bucket-name", "key", "target-bucket-name", "target-key"))
  .then(() => console.log("Data processed successfully"))
  .catch(console.error);
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

امیدوارم اکنون در مورد ایجاد و اجرای اثرات روشن باشیم. بیایید در قسمت بعدی ادامه دهیم ، جایی که ما به بررسی خطای کارآمد ، مدیریت همزمانی ، انواع داده های اثر ، مدیریت منابع و موارد دیگر خواهیم پرداخت. با ما همراه باشید!

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا