uz
Feedback

Firibgarlarga uchmang! Telemetrio bunday kanallarni topadi va belgilaydi 👉 Belgini ko‘rmoqchi bo‘lsangiz, obuna bo‘ling

HowProgrammingWorks - JavaScript and Node.js Programming

HowProgrammingWorks - JavaScript and Node.js Programming

Kanalga Telegram’da o‘tish

Программная инжененрия для JavaScript, TypeScrip, Node.js 👉 Group: https://t.me/How_Programming_Works 👉 Node.js channel: https://t.me/metarhia 👉 Node.js group: https://t.me/nodeua

Ko'proq ko'rsatish
6 575
Obunachilar
-724 soatlar
-47 kun
+5930 kun
Postlar arxiv
❓ В четверг 20 марта в 19:00 будет созвон сообщества Метархия, с выпускниками предыдущих наборов по паттернам, ноде и асинхронному программированию. Мы будем стримить его. Можно задать вопросы заранее и мы на них ответим. https://forms.gle/dDZTfR4P6AJFyHfB7

У кого не выходит выбрать язык на лендинге курса, можете сделать это в консоли, при помощи паттернов, самое базовое решение тут, но вы не останавливайтесь:
class Maybe {
  constructor(value) {
    this.value = value;
  }

  static of(value) {
    return new Maybe(value);
  }

  map(fn) {
    return this.value ? Maybe.of(fn(this.value)) : this;
  }

  getValue(defaultValue) {
    return this.value || defaultValue;
  }
}

class SelectCommand {
  constructor(selector, value) {
    this.selector = selector;
    this.value = value;
  }

  execute() {
    return Maybe.of(document.querySelector(this.selector))
      .map(el => (el.value = this.value, el))
      .map(el => el.dispatchEvent(new Event('change', { bubbles: true })))
      .getValue(null);
  }
}

const lang = 'RU'; // or UKR

new SelectCommand('.form-select-arrow', lang).execute();

🧩 Практический мастер-класс Паттерны в JavaScript и TypeScript ⏰ Начало: в эту субботу 2025-03-22 в 15:00 (Киевское время) 👳 Тимур Шемсединов 🥷 Илья Климов 🧔‍♂️ Дмитрий Нечай Изучение Патернов помогает: ✅ Писать более понятный код, который просто читать ✅ Эффективно оптимизировать JavaScript и TypeScript ✅ Быстрее и качественнее решать задачи ✅ Проектировать системы, которые просто изменять 🤖 Регистрация через Телеграмм-бот: https://patterns-js.com/0jiuic?traffic_mark=krzdaj

Скоро в метархии будет новый Emitter оптимизированый для V8, на него переедут протокод metacom, сервер приложений impress, и т.д. но вообще его полезно даже просто почитать: https://github.com/metarhia/metautil/blob/ee/lib/events.js
const ee = new Emitter();
ee.on('eventA', (data) => {
  console.log({ data });
  // Prints: { data: 'value' }
});
ee.emit('eventA', 'value');
const ee = new Emitter();
setTimeout(() => {
  ee.emit('eventA', 'value');
}, 100);
const result = await ee.toPromise('eventA');
const ee = new Emitter();
passReferenceSomewhere(ee);
const iterable = ee.toAsyncIterable('eventB');
for await (const eventData of iterable) {
  console.log({ eventData });
}



  listenerCount(eventName) {
    if (eventName) {
      return this.#events.get(eventName)?.length || 0;
    }
    const listeners = this.#events.values();
    return Array.from(listeners).reduce((acc, { length }) => acc + length, 0);
  }

  eventNames() {
    return Array.from(this.#events.keys());
  }
}

Скоро в Метархии будет оптимизированый для V8 новый Emitter, на который переедут стримы, протокод metacom, все другие части технологии, но его полезно даже просто пичитать: https://github.com/metarhia/metautil/blob/ee/lib/events.js
const DONE = { done: true, value: undefined };

class EventIterator {
  #resolvers = [];
  #emitter = null;
  #eventName = '';
  #listener = null;
  #onerror = null;
  #done = false;

  constructor(emitter, eventName) {
    this.#emitter = emitter;
    this.#eventName = eventName;

    this.#listener = (value) => {
      for (const resolver of this.#resolvers) {
        resolver.resolve({ done: this.#done, value });
      }
    };
    emitter.on(eventName, this.#listener);

    this.#onerror = (error) => {
      for (const resolver of this.#resolvers) {
        resolver.reject(error);
      }
      this.#finalize();
    };
    emitter.on('error', this.#onerror);
  }

  next() {
    return new Promise((resolve, reject) => {
      if (this.#done) return void resolve(DONE);
      this.#resolvers.push({ resolve, reject });
    });
  }

  #finalize() {
    if (this.#done) return;
    this.#done = true;
    this.#emitter.off(this.#eventName, this.#listener);
    this.#emitter.off('error', this.#onerror);
    for (const resolver of this.#resolvers) {
      resolver.resolve(DONE);
    }
    this.#resolvers.length = 0;
  }

  async return() {
    this.#finalize();
    return DONE;
  }

  async throw() {
    this.#finalize();
    return DONE;
  }
}

class EventIterable {
  #emitter = null;
  #eventName = '';

  constructor(emitter, eventName) {
    this.#emitter = emitter;
    this.#eventName = eventName;
  }

  [Symbol.asyncIterator]() {
    return new EventIterator(this.#emitter, this.#eventName);
  }
}

class Emitter {
  #events = new Map();
  #wrappers = new Map();
  #maxListeners = 10;

  constructor(options = {}) {
    this.#maxListeners = options.maxListeners ?? 10;
  }

  emit(eventName, value) {
    const listeners = this.#events.get(eventName);
    if (!listeners) return Promise.resolve();

    const promises = listeners.map((fn) => fn(value));
    return Promise.all(promises).then(() => undefined);
  }

  on(eventName, listener) {
    const listeners = this.#events.get(eventName) || [];
    if (listeners.includes(listener)) {
      throw new Error('Duplicate listeners detected');
    }
    listeners.push(listener);
    this.#events.set(eventName, listeners);

    if (listeners.length > this.#maxListeners) {
      throw new Error(
        `MaxListenersExceededWarning: Possible memory leak. ` +
          `Current maxListeners is ${this.#maxListeners}.`,
      );
    }
  }

  once(eventName, listener) {
    const wrapper = (value) => {
      this.off(eventName, listener);
      listener(value);
    };
    wrapper.origin = listener;
    this.on(eventName, wrapper);
    this.#wrappers.set(listener, wrapper);
  }

  off(eventName, listener) {
    if (!listener) return void this.clear(eventName);

    const listeners = this.#events.get(eventName);
    if (!listeners) return;

    const keep = (f) => f !== listener && f !== this.#wrappers.get(listener);
    const updated = listeners.filter(keep);

    this.#events.set(eventName, updated);
    this.#wrappers.delete(listener);
  }

  toPromise(eventName) {
    return new Promise((resolve) => {
      this.once(eventName, resolve);
    });
  }

  toAsyncIterable(eventName) {
    return new EventIterable(this, eventName);
  }

  clear(eventName) {
    if (!eventName) {
      this.#events.clear();
      this.#wrappers.clear();
      return;
    }
    const listeners = this.#events.get(eventName);
    if (!listeners) return;
    for (const listener of listeners) {
      this.#wrappers.delete(listener);
    }
    this.#events.delete(eventName);
  }

  listeners(eventName) {
    if (eventName) {
      const listeners = this.#events.get(eventName) || [];
      return listeners.map((listener) => listener.origin || listener);
    }
    return Array.from(this.#events.values()).flat();
  }

На что вы всегда найдете время?
Anonymous voting

Когда внук начал программировать на TypeScript, дедушка переписал на суслика свою квартиру
Когда внук начал программировать на TypeScript, дедушка переписал на суслика свою квартиру

В чем преимущество этого фреймворка? - нет ничего лишнего - все очень просто - мы решили все проблемы - добавлены удобные фишки - исправлены почти все баги - заехала новая архитектура папочек - поддержка TS через удаление типов - чтобы писать ни нужно знать ничего, ведь это будущее...

💡 Как сделать новый популярный фреймворк: 1. Взять один случайный паттерн 2. Дать ему неузнаваемое название 3. Сделать презентацию, пообещав всем, что это и есть решение всех проблем