0

I was working on AngularJS 1.5.3 project, and I'm having trouble with chaining promises.

I have a function that looks like that;

this.login = function(u,p){ var promise=$auth.login(u,p).then(...); return promise;}
this.tests = [
    ['Im LoginController, i let users login'],
    ['I have logs attr, to bind current state to view',null,function(){return !!angular.isArray(self.log)}],
    ['I have $auth attr, that expse the $auth service',function(){return !!(self.$auth===$auth)}],
    ['I can get tokens from server',null,function(){return self.login({u:1,pass:1234})},function(){return !!($auth.currentUser.id === 1 && $auth.currentUser.hasValidToken()===true)}
];

I think you can see what I'm trying here...

So the array is composed of

[
    0 => string
    1 => a function that return promise
    2 => a function that confirms that the previous function effects took place
]

I wanted to create a directive to autotest controllers presenting visual aids- anyhow-,

What I need is to loop the array and execute them in order and return true/false for [1,2];

My first attempt was directly into Angular1 template using ngRepeat

<ul>
  <li ng-if="$last ng-repeat="test in tests">{{test[0]}} :: {{test[1]() && test[2]()}}</li>
</ul>

Failed very bad, because of course they don't execute in order. So I realized I need to wrap them in promises ?

2
  • If tests is an array then it will iterate them in what ever order the array is in, if its iterating an object thats when the order can't be guaranteed. However with an ng-repeat they will all execute pretty much at the same time. Have a look at $q.all if thats desired as this will do it all in code rather than relying on angular bindings. Would make it easier to test. Commented Apr 6, 2016 at 6:45
  • @ste2425 array contain array, and mixed values 'string,function' $q.all can handle all that ? Commented Apr 6, 2016 at 6:52

1 Answer 1

1

You could execute all tests in a controller before rendering them with ng-repeat and then using $q.all() make sure they all are resolved while storing their results in a separate variable. In particular something along these lines:

var testCases = [
    ['Im LoginController, i let users login'],
    ['I have logs...', null, function(){return !!angular.isArray(self.log)}],
];

var promises = [];

scope.testResults = [];
scope.testsExecuted = false;

for (var i = 0; i < this.pendingScenarios.length; i++) {
    var testCase = this.testCases[i];
    if (testCase[1]) {
        var result = $.when(testCase[1]());
        result.then(function(result) {
            testResults[i] = result;
        });
        promises.push(result);
    }
    // ...
}

$q.all(promises).then(function() {
    $scope.testsExecuted = true;
});

I didn't test the code but I think you get the idea. If the test returns a Promise you put it into an array and at the end make sure they all are resolved while result.then() storing its result.

Sign up to request clarification or add additional context in comments.

2 Comments

You could use $q.when to wrap non promises in a promise then you don't need to check yourself but $q.all will also do this. Then you can pass an array of promises into $q.all and let it combine the results for you. $q.all will resolve with all the resolved values from the array of promises. So you don't need to do that yourself either. jsfiddle.net/29n63c1s
@ste2425 thanks for the fiddle, yet all functions return null when wrapped in $q.when() any idea why ? var promises = [$q.when(function(){ return 10; }), $q.when(function(){return true}) , .. or any function will always return null, even if it returns a $q.when

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.