Использование $filter в директиве Angular

Я разработал директиву Angular для отображения визуализации D3. Я использую $filter в функции tickFormat на моей оси y так:

ySalesAxis = d3.svg.axis()
  .orient('left')
  .ticks(6)
  .scale(ySalesScale)
  .tickFormat(function(d) {
    return $filter('formatSalesValue')(d.value, 'USD');
  });

Проблема, которую я вижу, заключается в том, что ни одна из этих меток не появляется, когда страница загружается первой. Действительно, если я console.log($filter('formatSalesValue')(d.value, 'USD')), я получаю 6 undefined (так как для свойства ticks установлено значение 6). Однако, как только я предпринимаю действие, щелкнув внутри фильтра кисти, например, метки ярлыков отображаются правильно отформатированными.

введите описание изображения здесь

Мой фильтр formatSalesValue вызывает службу (асинхронная операция), потому что в систему и из нее задействованы десятки валют, подробности о которых я извлекаю из БД. Я уверен, что по этой причине мои метки ярлыков undefined. Что я могу сделать, чтобы убедиться, что эти значения отображаются сразу после загрузки страницы? Примечание. Я попытался обернуть мою функцию tickFormat при вызове scope.$apply, но я получаю ошибку digest already in progress.

Ответы

Ответ 1

Метод Axis tickFormat запускает обратный вызов и использует значение, возвращаемое им синхронно. Вот почему вы получаете undefined при первом вызове, так как ваш $фильтр является асинхронным.

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

Если вы сделаете JSBin, я, вероятно, расскажу вам больше.

Ответ 2

TL; DR

Попробуйте использовать функцию Angular $timeout.


Исходя из вашего вопроса, проблема может быть любым количеством вещей, но это то, что я считаю проблемой:

Возможная проблема

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

$timeout - это полезные функции, поскольку он выполняется, когда текущий стек очищается и после прохода n миллисекунд, если нет времени на задержку данный, $timeout просто запускается, как только пакет распаковывается. Это полезный трюк для выполнения асинхронного кода в одном потоке.

Использование $timeout с задержкой 0 на самом деле не означает, что обратный вызов будет погашен после нулевого миллисекунды. Я просто запускаю выполнение после обработки очереди задач. Это когда вы хотите обновить свои метки.

$timeout фактически вызовет дайджест, когда он будет готов к этому.

Возможное решение

$timeout(function() {
  // Update the label with what comes back from the server
}, 0, false);

Это хорошее видео, объясняющее, как работает цикл событий Javascript: Какая черта в цикле событий?