Method dekorator — metodlarni wrapping qilish

~20 daq · TypeScript · Dekoratorlar

Har metod chaqiruvini log qilish kerak. Har metodga console.log yozish takror. Method dekorator — metodni bir marta @Log bilan belgilash, log avtomatik.


Method dekorator imzosi

type MethodDecorator = (
  target:      Object,       // prototype
  key:         string,       // metod nomi
  descriptor:  PropertyDescriptor // metod tavsifi
) => PropertyDescriptor | void;

Log dekorator

function Log(
  target:     Object,
  key:        string,
  descriptor: PropertyDescriptor
): PropertyDescriptor {
  const aslMetod = descriptor.value; // asl funksiyani saqlaymiz

  descriptor.value = function(...args: any[]) {
    console.log(`${key} chaqirildi, argumentlar:`, args);
    const natija = aslMetod.apply(this, args);
    console.log(`${key} natija:`, natija);
    return natija;
  };

  return descriptor;
}

Ishlatish:

class Hisoblash {
  @Log
  qoshish(a: number, b: number): number {
    return a + b;
  }
}

const h = new Hisoblash();
h.qoshish(2, 3);
// "qoshish chaqirildi, argumentlar: [2, 3]"
// "qoshish natija: 5"

Vaqt o'lchash

function Vaqt(target: Object, key: string, descriptor: PropertyDescriptor) {
  const asl = descriptor.value;

  descriptor.value = async function(...args: any[]) {
    const boshlash = Date.now();
    const natija = await asl.apply(this, args);
    console.log(`${key}: ${Date.now() - boshlash}ms`);
    return natija;
  };

  return descriptor;
}

class ApiXizmat {
  @Vaqt
  async foydalanuvchilarOl(): Promise<any[]> {
    return fetch("/api/users").then(r => r.json());
  }
}

Xato ushlash — try/catch

function XatoUshlash(target: Object, key: string, descriptor: PropertyDescriptor) {
  const asl = descriptor.value;

  descriptor.value = async function(...args: any[]) {
    try {
      return await asl.apply(this, args);
    } catch (err) {
      console.error(`${key} da xato:`, err);
      throw err; // yoki null qaytarish
    }
  };

  return descriptor;
}

Parametrli method dekorator

function MinDaraja(min: number) {
  return function(target: Object, key: string, descriptor: PropertyDescriptor) {
    const asl = descriptor.value;

    descriptor.value = function(qiymat: number) {
      if (qiymat < min) {
        throw new Error(`${key}: ${qiymat} < ${min}`);
      }
      return asl.call(this, qiymat);
    };

    return descriptor;
  };
}

class Hisobot {
  @MinDaraja(0)
  yilliqHisobot(yil: number): string { return `${yil} yil`; }
}

new Hisobot().yilliqHisobot(-1); // ❌ xato
new Hisobot().yilliqHisobot(2024); // ✅

Xulosa

function MyDeco(target: Object, key: string, desc: PropertyDescriptor) {
  const asl = desc.value;

  desc.value = function(...args: any[]) {
    // oldin...
    const natija = asl.apply(this, args);
    // keyin...
    return natija;
  };

  return desc;
}

@MyDeco metodNomi() {}

Method dekorator — metodga o'zgartirish kiritmasdan, wrapper qo'shish. Log, vaqt o'lchash, xato ushlash, cache uchun ideal.


Keyingi dars

56-dars: Property dekorator — xususiyatlarni boshqarish