0

I have a controller which calls a service, the service does an async work, when the work (Promise) is done I set a property on the controller's scope object.

function TodoController(TodosService) {
    let self = this;

    TodosService.fetchTodos().then((todos) => (self.todos = todos));
    
    ... other code here

  }

The problem is that using async/await in the service does not update the html rendered elements after the promise is resolved, but using then works normally and updates the rendered elements with the fetched todos:

    app.service("TodosService", function ($http) {

    // This code does not work, it fetches the todos successfully and also the controller succesfully sets them as a property, but no visual change happens

    // this.fetchTodos = async function () {
    //   let json = await $http.get("...");
    //   return json.data["todos"];
    // };

    // This code works normally as explained above
    this.fetchTodos = () =>
      $http
        .get("...")
        .then((json) => json.data["todos"]);
  }

What is the difference between the two cases, because AFAIK (I'm new to JS) both an async function and $http.get(...).then(...) will return promises, so what am I missing here?

8
  • A function that uses .then() will only return a promise if it actually has a return statement. Commented Jul 24, 2022 at 22:22
  • 1
    @Pointy in my actual code I used return in the then section, but here I used arrow functions for brevity only. Also I want to mention that I printed the return value of both approaches (the async/await and the .then ) and both printed object Promise, but why is one Promise updating the html visuals and the other is not? Commented Jul 24, 2022 at 22:26
  • Not in the .then() callback. The containing function must return the result of the Promise chain, or else it returns undefined. Commented Jul 24, 2022 at 22:41
  • @Pointy can you clarify more what you mean, do you mean that fetchTodos in the async/await case is not returning a Promise? I printed the return value of fetchTodos() in the controller and in both cases a promise was returned and the callback was invoked after some waiting time? Commented Jul 24, 2022 at 22:47
  • If you're trying to access self.todos in that "other code here" block, that will not work. The call to .then() will return immediately, before the Promise is resolved. Commented Jul 24, 2022 at 22:52

1 Answer 1

1

await ~wraps you code into native Promise and put later code into callback.

$http runs http request and then triggers $digest

So line TodosService.fetchTodos().then((todos) => (self.todos = todos)); when u use await will:

  • run http request
  • run digest
  • change controller todos field

And as u see digest will not see your changes.

P.S. Things can be a bit more complicated as $http may trigger async digest (when useApplyAsync is set to true) and then this code may actually work with await sometimes(?) but is unreliable anyway.

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

1 Comment

Really weird behaviors

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.