4

I load some data for multiple users and I want to store it into a javascript array. In pure typescript, I will write it like that:

for(var i = 0; i < 5; i++) {
   promise[i] = httpquery.then( 
     (data) => { this.usersData[i] = data }
   );
)

...

this.$q.all[promise].then(......

unfortunately, my typescript lambda protect only this (and not the variable i). So in my case it will always store the data in this.usersData[5].

Right, I need a closure, and what lambda expression do is a bit similar to a closure as far as I understand this typescript's part of language.

so let try to do something with Typescript :

for(var i = 0; i < 5; i++) {
   promise[i] = (index = i) => {
       return httpquery.then( 
          (data) => { this.usersData[index] = data }
       );
   }();
)

which not work at all (not even compile). Why ? because seems that () => {} is not really a function. I solved this by using this way :

for(var i = 0; i < 5; i++) {
   var getData = (index = i) => {
       return httpquery.then( 
          (data) => { this.usersData[index] = data }
       );
   };
   promise[i] = getData();
)

which I found not super beautiful :-p. So my question is: how to proceed in this case of issue ? Like I did ? Or there is a way to use the lambda in typescript in a more beautiful way ? And why

 () => {}() 

isn't working but

 var test = () => {}; 
 test(); 

works ? It it because of the typescript compiler which is not "smart" enough to understand that the lambda is a function ?

Thanks.

1 Answer 1

3

The reason why:

promise[i] = (index = i) => {
  return httpquery.then( 
    (data) => { this.usersData[index] = data }
  );
}();

doesn't parse is because it isn't valid JavaScript (var x = a => { return a + 1; }(3) is a SyntaxError in JavaScript as well as TypeScript. Simply wrapping the lambda in parenthesis is enough to make it a valid expression.

However, simply doing that will not fix your capturing issue - default arguments are evaluated on each call, and so they will all point at the final bound value of the var.

Instead you can either:

A) Switch to using let in your initializer (in which case TypeScript will automatically do the right thing:

for(let i = 0; i < 5; i++) {
  promise[i] = httpquery.then(data => this.usersData[i] = data);
}

B) Manually create the closure yourself:

for(var i = 0; i < 5; i++) {
  promise[i] = (index => httpquery.then(data => this.usersData[index] = data))(i);
}
Sign up to request clarification or add additional context in comments.

1 Comment

Indeed, using let is the most beautiful solution. I still use var and didn't take the time to look at let/const, and I think is the right time to change this bad habit. Thanks !

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.