Angular $ q然后地狱

时间:2014-10-07 21:32:51

标签: javascript angularjs asynchronous angular-promise

在角色的Q实现中,我们怎么能让这种呼叫看起来更好?在这种情况下,d3加载与数据加载无关,它应该是平行的。

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

这种有臭味的代码也很难测试,因为有多种承诺需要模拟。任何代码测试的最佳实践?

2 个答案:

答案 0 :(得分:4)

由于第二个承诺似乎不依赖于第一个承诺,因此您可以并行运行它们并在两个承诺完成后使用$q.all()调用函数。

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

在上面的例子中,我们创建了一个对象,因此我们可以使用这些键来引用每个promise的结果。您还可以传递一系列承诺。对于数组(如下),结果将是一个结果数组,其顺序与promises相同。

$q.all([d3Q.init(), scope.loadHistoryData()])
    .then(function(result) {
        scope.renderHistoryGram(target, result[0], result[1]);
    });

答案 1 :(得分:1)

最简单的方法,不要过多考虑它:

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);
    });