Reputation: 94
In angular's Q implementation, how could we make this kind of call looks better? In this case, d3 loading has nothing to do with data loading, it should be paralleled for sure.
d3Q.init()
.then(function(d3) {
scope.loadHistoryData()
.then(function(data) {
scope.renderHistoryGram(target, data, d3);
});
});
This kind smelly code is also hard to test because there are multiple promise need to mock. Any best practice for the code testing?
Upvotes: 3
Views: 255
Reputation: 25726
Since it doesn't appear that the second promise depends on the first, you can run them in parallel and call a function after both have finished using $q.all().
$q.all({d3: d3Q.init(), data: scope.loadHistoryData()})
.then(function(result) {
scope.renderHistoryGram(target, result.d3, result.data);
});
In the case above, we created an object so we can use the keys to reference the result of each of the promises. You can also pass in an array of promises. In the case of an array (below), the result will be an array of result in the same order as the promises.
$q.all([d3Q.init(), scope.loadHistoryData()])
.then(function(result) {
scope.renderHistoryGram(target, result[0], result[1]);
});
Upvotes: 3
Reputation:
The simplest way, without thinking too much about it:
d3Q.init()
.then(function(d3) {
return scope.loadHistoryData();
}).then(function(data) {
scope.renderHistoryGram(target, data, d3);
});
Instead of acting on the promise inside your handler, you return it to the "parent" context, if that makes sense.
The other way to do this would be to write your scope handler to take d3
as an argument, so you could do this:
d3Q.init()
.then(scope.loadHistoryData)
.then(function(data) {
scope.renderHistoryGram(target, data, d3);
});
Upvotes: 1