Angular.js: Поддержка асинхронного модуля .run ()

Созданный на 13 сент. 2013  ·  62Комментарии  ·  Источник: angular/angular.js

Мы хотим выполнить несколько вызовов $ http в блоке выполнения модуля, в идеале выполнение должно завершаться только после завершения $ http и обработки до того, как произойдет компиляция dom.

Lots of comments won't fix feature

Самый полезный комментарий

jfcfxekzl5m
Простая функция, но ее сложно реализовать. 😕

Все 62 Комментарий

Это не так-то просто, но следует рассмотреть.

Жасмин делает это путем установки флага, который позволит функции запускаться и ждать обратного вызова, пока флаг не будет установлен в true или пока не сработает тайм-аут.

В основном примерно так:

var flag = false;
$http(...).success(flag = true);
$timeout(function () {
    flag = true;
    // Or add some error handling stuff here
}, 5000);
while (!flag) {};

Это некрасиво, но должно работать. Приведенный выше код не тестировался, поэтому вам может потребоваться его немного изменить. Здесь уже поздно. Надеюсь, что-то поможет вам, пока не появится что-то более красивое.

+1

В какой-то момент это действительно приводит к невозможности нарисовать причудливый экран загрузки с помощью директив angular ...

+1

Разве $routeProvider с resolve решает эту проблему? Может я не понял в чем проблема ...

Это больше для поддержки инициализации асинхронного модуля. С учетом сказанного, мне это больше не нужно в моих текущих проектах.

@shahata $routeprovider делает это, но не каждый вариант использования обещания run s использует маршруты. В моем случае это для модуля, который является оболочкой для директивы и не имеет ничего общего с маршрутами.

+1

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

+1

+1 досадно, что это проигнорировали

есть идеи, когда он приземлится? так неприятно перемещать элементы инициализации для разрешения в маршрутизаторе, в основном потому, что иногда код инициализации не зависит от URL-адреса (он же должен быть инициализирован для любого типа URL-адреса, который пользователь приходит в ваш SPA)

Я не думаю, что с этого момента angular получит какие-либо улучшения. все они добавляются в angular 2.0

как долго недоделанный метод run будет оставаться синхронным? Хорошо и понятно, что config не поддерживает асинхронные вызовы, поскольку у вас нет провайдеров, которые выполняют вызовы $http , а run поддерживает. посмотрите, какие взломы вызваны отсутствием этой функции (которая должна была присутствовать с самого начала)
https://github.com/philippd/angular-deferred-bootstrap/blob/master/src/deferred-bootstrap.js

это неловко

+1

@btford изучает, как варианты использования вокруг этого могут поддерживаться через новый маршрутизатор, а не внутри блоков выполнения.

+1

+1

+1

+1

Основная проблема заключается в том, что $q создается внутри модуля, который загружается при запуске runBlocks. Это означает, что нам нужно будет каким-то образом извлечь «некоторые» службы (или, возможно, модули) и сначала создать их, а затем выполнить второй проход, который загружает остальные модули (и службы, блоки запуска и т. Д.) После того, как $ q был создан.

@lgalfaso - возможно, вы могли бы изучить это немного подробнее в рамках своей $injector работы позже на этой неделе (или на следующей)?

Я знаю, что это всего лишь обходной путь, но обычно я решал проблему наличия некоторой логики асинхронной начальной загрузки с помощью маршрутизатора angular ui и наличия корневого абстрактного состояния в сочетании с разрешением. Первым всегда должно быть разрешено корневое абстрактное состояние, поэтому это хорошее место для загрузки настроек, отображения анимации загрузки и т. Д.

Это было бы действительно здорово.
: +1:
Жду этого исправления. Надеюсь, что он появится в 1.4

+1

У меня есть еще один вариант использования: мне нужно запустить мои смоделированные конечные точки с помощью вызова $ http при запуске (для кеширования некоторых данных) ...

+1

+1

просто наткнулся на это тоже ...

@petebacondarwin, думаю, можно продолжить загрузку всех остальных модулей, но отложить

в качестве альтернативы $ routeProvider может предложить настраиваемый параметр функции, который должен отложить рендеринг начального маршрута.

+1

+1

Вот возможный обходной путь: http://plnkr.co/edit/vi7mDjmD4NpZAoP7MVzr?p=preview
Идея состоит в том, что Angular фактически дает вам возможность создать собственный инжектор из набора модулей. В этом случае я отложил компиляцию $rootElement до тех пор, пока не будут выполнены несколько обещаний ( resolves ). Это POC, и будет ряд других наворотов, которые понадобятся, чтобы подготовить эту постановку. Помимо всего прочего, вам нужно будет ловить ошибки в разрешении, а не просто проглатывать их.

+1

Это в основном руководство для тех, кто хочет попробовать; В настоящее время процесс начальной загрузки выполняет следующие действия:

  • Проверки на вменяемость
  • Создает произведенный за $rootElement
  • Создает инжектор
  • Компилирует и связывает $rootElement

Сверху, при создании инжектора шаги следующие:

  • Обход дерева модулей зависимостей и

    • Инициализация модуля, которая будет регистрировать константы модуля, значения, провайдеры и другие вещи.

    • Запуск функций конфигурации

    • Соберите run функции на будущее

  • Запустить все run функции

Вот несколько ключевых моментов:

  • Все блоки run выполняются до компиляции $rootElement
  • В процессе создания инжектора нет циклов дайджеста, первый цикл дайджеста происходит во время начальной компиляции $rootElement
  • $q разрешает обещания во время цикла дайджеста _only_

Это:

  • Если есть модуль, который имеет функцию run которая возвращает обещание, и обещание должно быть разрешено до запуска приложения, то перед начальной компиляцией будут циклы дайджеста (это может нарушить существующие приложения)
  • Блок конфигурации не может вернуть обещание, поскольку функция config вводится поставщиками, а не экземплярами

Какое бы ни было решение, необходимо обрабатывать эти случаи

+1
любые новости?
Я просто хочу загрузить некоторые настройки конфигурации до того, как приложение действительно запустится.

+1

Я бы загрузил некоторые асинхронные данные после начальной загрузки, когда все мои фабрики работают, и до компиляции.

@dagingaa : Я бы выбрал ваше решение в качестве обходного пути! Благодарность

  • 1

Обновление до @dagingaa : цикл for замораживает мои браузеры, не очень хорошо ...

https://jsfiddle.net/tuxmachine/t4d63vnw/

Вот как я решил это для реализации токена OAuth, которая требовала разрешения первоначального вызова ajax перед инициализацией остальной части приложения.

Не будет работать, если у вас есть несколько блоков асинхронного запуска.

+1

+1

+1

Прошло два года с момента открытия вопроса, но до сих пор нет хорошего решения

@vladmiller Есть решения, но, возможно, вы не чувствуете, что они хороши:

  • используйте ngRoute или ui-router с resolves и поместите код запуска вашего приложения внутри маршрута верхнего уровня
  • создайте свой собственный асинхронный загрузчик. см. https://github.com/angular/angular.js/issues/4003#issuecomment -113842180
  • использовать новый компонентный маршрутизатор с $onActivate в компоненте верхнего уровня

Помещение нетривиальной работы приложения в блоки .run затрудняет модульное тестирование вашего кода. Так что мы не хотим поощрять это. Перенести это в Ice Box мы вряд ли сможем.

@petebacondarwin Я бы с вами не согласился; все ожидают, что angluar будет простым и интуитивно понятным, вместо этого вам нужно либо реализовать свой собственный модуль начальной загрузки async, либо модуль начальной загрузки в другом месте. На мой взгляд, это усложняет angular.

Можете ли вы также объяснить, что вы имеете в виду, когда говорите, что асинхронный код в .run затруднит тестирование?

Извиняюсь за мой предыдущий грубый комментарий.
Спасибо

@petebacondarwin Я не понимаю, как это затрудняет тестирование. если вы поместите код инициализации в службу, вы можете просто посмотреть / имитировать / сравнить результаты, которые вы ожидаете от макета HTTP-бэкэнда, независимо от того, выполняется он внутри блока .run или нет. наличие кода за пределами angular из-за обходных путей из-за отсутствия асинхронного запуска - вот что делает практически невозможным тестирование

Как дела?

Решение @petebacondarwin сработало для меня

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

jfcfxekzl5m
Простая функция, но ее сложно реализовать. 😕

+1 за эту функцию

+1

+1

Решение @petebacondarwin работает хорошо.

+1. :(

+1

+1

+1

+1

Мы не собираемся этого делать.

+100, все обходятся ужасно.

@ Eduardo-Julio - мы не собираемся реализовывать эту функцию, так как это значительно усложнит загрузку приложений AngularJS. Добавление дополнительных + s не поможет.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги