Pull to refresh

Comments 38

Уже везде есть глобальная переменная globalThis.

Хорошо, окей, а если мне в блоке инициализации приложения нужно пользоваться async/await?


Пока что получается такая конструкция:


(async () => {
  await someDatabaseInit()
  await someCacheInit()
  // ...
})()

Дельный комментарий на самом деле.


Не нужно забывать об обработке ошибок, await нужно обернуть в try/catch, и конструкция получается более громоздкой чем цепочка с .then/catch

обработку then можно почти всегда опустить, а вот catch все же нужен. В браузере вполне приемлемо использовать такую конструкцию и при желании можно прокинуть нормальный обработчик


window.onerror = e => {
  // тут может оказаться нормальный обработчик
  console.error(e)
}
(async () => {
  // ...
  throw new Error('catch me')
})().catch(onerror)</source>

Это не сработает. onerror не будет ловить ошибки, которые возникают в цепочке промисов. Для этого нужно использовать window.onunhandledrejection либо window.addEventListener("unhandledrejectuin", ...). FF начал поддерживать эти обработчики только в конце 2019 года, а Safari до сих пор не поддерживает 2-ой способ

Вполне работает, только как я и написал, нужно будет каждый раз catch с onerror явно прописывать. Но `unhandledrejectuin` все же предпочтительнее, соглашусь

Кстати, можно еще так:


const promise = (async () => {
  await someDatabaseInit()
})()

promise.catch(console.error)

Использую асинхронные замыкания чаще всего в React-хуках.

Тоже об этом вспомнил. Но похоже, это единственный случай, когда IIFE целесообразен.

Тем, что исключения ловить обязательно

Их и так ловить приходится (.catch), только немного в другом виде. Принципиальной разницы не вижу
Вроде собираются сделать, чтобы можно было await использовать на уровне модуля, не оборачивая в async функцию.
Уже Stage 3. Значит сделают.
github.com/tc39/proposal-top-level-await
По ссылке что я приложил используется «высасывание». Добавил и ваш источник
Да. И для того что бы понять о чем идет речь мне пришлось по этой ссылке перейти. В то время как «поднятие» или «hoisting» все же более привычное определение этому явлению.

Бритва Оккама…

P. S. Спасибо за правку первоначального поста
А ничего, что вебпак все модули в IIFE заворачивает?

Пусть делает, что должен. Это же инструмент. При минификации тоже происходит много вещей, которые не нужно делать руками. Так и тут — речь про то, что не нужно самим писать IIFE.

В примере в статье как раз показан пример. Замыкание возвращает функцию, которая изменяет значение переменной count, объявленой снаружи этой функции. Это и есть побочный эффект в терминологи функционального программирования.
переменная count является частью замыкания и не объявлена вне замыкания, следовательно замыкание не имеет побочный эффект. count является «приватным свойством» замыкания.
Замыкание являются частью ФП. И не нарушает принципов ФП
переменная count является частью замыкания и не объявлена вне замыкания

Верно. Так же верно то что, переменная count объявлена снаружи функции, которую возвращает замыкание.

https://en.wikipedia.org/wiki/Side_effect_(computer_science)
Первый абзац:
function or expression is said to have a side effect if it modifies some state variable value(s) outside its local environment, that is to say has an observable effect besides returning a value (the main effect) to the invoker of the operation

В нашем фрагменте когда функция, которая возвращается замыканием, изменяет состояние (переменную count), которая объявлена все этой функции. Это называется побочным эффектом.

Или вот отсюда: Побочный эффект (программирование)
Если вызвать функцию с побочным эффектом дважды с одним и тем же набором значений входных аргументов, может случиться так, что в качестве результата будут возвращены разные значения.

Если вы вызовем функцию id() из нашего примера дважды (с одним и тем же набором аргументов; если быть точным не передавая никаких аргументов), то она вернёт нам разный результат. Это нарушает принцип ФП. Причиной является то, что функция id() имеет побочный эффект.
я бы лучше предложил перестать использовать классы (ой прости господи за не популярное мнение)
У меня тоже такое не популярное мнение. Но не потому что классы плохие для всего, а потому что в JS имеют особенности. Например мне не нравится прототипное наследование, имеющее контекст только в виде самого объекта и вечного this, и не позволяющее собрать объект несколькими конструкторами и делать в него примеси или замены полей без всякой иерархии (оставляя объект плоским одноуровневым).
вот именно, в JS свои особенности и свои практики. Пришли новые люди — принесли свои практики которые плохо сюда заходят и создали кашу. Сам был в ряду таковых (:facepalm:)
не нравится прототипное наследование, имеющее контекст только в виде самого объекта и вечного this, и не позволяющее собрать объект несколькими конструкторами и делать в него примеси или замены полей без всякой иерархии


А как бы вам нравилось чтобы это работало? Интересно понять как вы видите удачное решение этой задачи.
Вот обычный принцип, который работал испокон веков (осовременен):

function FirstConstructor(){
    const t = this;
    let privateVar = 123;
    t.publicMethod = val => privateVar + val; // никаких this для приватных полей
}
function SecondConstructor(){
    const t = this;
    let privateVar = 456; // приватные поля не пересекутся с родителем
    delete t.publicMethod; // удаляем метод и его в объекте не будет нигде
    t.anotherPublicMethod = ()=> privateVar; // никаких this для приватных полей
    function privateMethod(){ return privateVar } // нет this для приватных полей
    t.thirdPublicMethod = ()=> privateMethod() + 7; // нет this для прив. методов
}
let myInstance = new FirstConstructor();
SecondConstructor.call( myInstance );

В результате выходит экземпляр, у которого нет прототипов (кроме стандартного), всё на одном уровне, честные приватные поля, работающие без this.#, и удалённый метод. Есть конечно недостатки, и их не мало, но и преимущества есть.
Полностью отказываться от этого подхода не стоит. У него по-прежнему остались применения. Например скоуп для сиюминутных локальных функций, работающих с общей локальной переменной. Или например вычисление значения для ключа при написании объекта литералом. Эти случаи конечно можно обходить иначе, но есть нюансы.
Или например вычисление значения для ключа при написании объекта литералом.

Для этого напрашиваются template strings. Какие с ними могут быть нюансы?
let obj = {
    myKey: (()=>{
        if( !someCheck() ) return;
        ...
        return result;
    })
}

А где тут IIFE? Да и то сократить можно


let obj = {
    myKey(){
        if( !someCheck() ) return;
        ...
        return result;
    }
}

Если забыли добавить (). То это костыльный способ заменить do exressions

В моём примере функция в скобках вызывается до создания ключа и записывает в ключ готовое значение. А в вашем примере это метод, а не свойство, он каждый раз вычисляет что-то, а не содержит готовое значение.
Пардон, забыл после скобок (), так что вы правы
UFO just landed and posted this here
Без этого пришлось бы вычислять ключ выше. С одной стороны литерал смотрелся бы чище, но с другой — всё в разных местах и приходится собирать логику по кускам.
Sign up to leave a comment.