Угловой $q, тогда ад

В реализации angular Q, как мы могли бы сделать такой вызов лучше? В данном случае загрузка d3 не имеет ничего общего с загрузкой данных, она обязательно должна быть распараллелена.

 d3Q.init()
    .then(function(d3) {
        scope.loadHistoryData()
            .then(function(data) {
                scope.renderHistoryGram(target, data, d3);
            });
    });

Этот вонючий код также трудно тестировать, потому что есть несколько промисов, которые нужно имитировать. Любая лучшая практика для тестирования кода?


person Peng    schedule 07.10.2014    source источник


Ответы (2)


Поскольку не похоже, что второе обещание зависит от первого, вы можете запустить их параллельно и вызвать функцию после того, как оба завершат использование $q.all().

$q.all({d3: d3Q.init(), data: scope.loadHistoryData()})
    .then(function(result) {
        scope.renderHistoryGram(target, result.d3, result.data);
    });

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

$q.all([d3Q.init(), scope.loadHistoryData()])
    .then(function(result) {
        scope.renderHistoryGram(target, result[0], result[1]);
    });
person TheSharpieOne    schedule 07.10.2014
comment
На самом деле, это лучший ответ, чем мой собственный. Проголосовал. - person jedd.ahyoung; 08.10.2014
comment
Мое невежество! Я должен сначала прочитать документ. я еще нуб. Спасибо, что сделали мой день. - person Peng; 08.10.2014

Самый простой способ, особо не задумываясь:

d3Q.init()
    .then(function(d3) {
        return scope.loadHistoryData();
    }).then(function(data) {
        scope.renderHistoryGram(target, data, d3);
    });

Вместо того, чтобы действовать в соответствии с обещанием внутри вашего обработчика, вы возвращаете его в «родительский» контекст, если это имеет смысл.

Другой способ сделать это — написать обработчик области действия, который принимает d3 в качестве аргумента, поэтому вы можете сделать это:

d3Q.init()
    .then(scope.loadHistoryData)
    .then(function(data) {
        scope.renderHistoryGram(target, data, d3);
    });
person jedd.ahyoung    schedule 07.10.2014
comment
Спасибо за ответ. Это мой первый подход, на самом деле он такой. d3Q.init() .then(function(d3){ scope.d3=d3; }) Затем используйте scope.d3 в функции рендеринга. Я ненавижу добавлять это к глобальному. поэтому я продолжал пытаться найти лучший способ. - person Peng; 08.10.2014