Future is completed before function-call is done

587 Views Asked by At

I'm working with two functions, both of them should return a future. A third function gets called when both of them are done. Right now the future is returned too early, so that my third function is called before my second function is completed.

Function1:

static var getObjectDataCompleter = new Completer();
static var fillObjectCompleter = new Completer();

static Future getObjectData(List jsonMap) {

  for (int i = 0; i < jsonMap.length; i++) {
    fillObjectCompleter = new Completer();
    var request = buildRequest("GET", resourceUrl);
    request.send();
    request.onLoadEnd.listen((event) => fillObject(request));
  }

  if(fillObjectCompleter.isCompleted) {
    getObjectDataCompleter.complete(null);
  }

  return getObjectDataCompleter.future;
}

Function2:

static Future fillObject(HttpRequest request) {
      String responseText = request.response;
      List stringJson = JSON.decode(responseText);
      fillObjectCompleter.complete(null);
      return fillObjectCompleter.future;
}

Function1 is returning the future before the call "fillObject()" is completed.
What am I doing wrong?
The function1-future should be returned when the "for-loop" is done and all "fillObject-calls" are completed.

1

There are 1 best solutions below

0
On BEST ANSWER

Async code is just scheduled for later execution and the sync code continues executing without waiting for the async code. The method you pass ot Future.then(...) is executed when the scheduled async code is finished. You find a lot of such questions and examples tagged [:dart-async:] here on StackOverflow.

I have a hard time figuring out what you actually try to accomplish. Can you please explain in prosa what you actually try to accomplish, then I can try to fix your code example to do what you want it to do.

Usually there is no need to use a Completer in custom async functions. You just have to ensure that nested async calls are properly chained by always returning the future of the call.
See these two lines of the following code as example. The returns are important for the example to work.

return async.Future.forEach(jsonMap, (item) {
return request.onLoadEnd.first.then((event) => fillObject(event.target));

The Future returned from getObjectData completes after the response of all requests are processed.

import 'dart:html' as dom;
import 'dart:async' as async;
import 'dart:convert' show JSON;

class Xxx {

  static async.Future getObjectData(List jsonMap) {

    return async.Future.forEach(jsonMap, (item) {
      //var request = new dom.HttpRequest();
      //request.open("GET", "https://www.googleapis.com/discovery/v1/apis?fields=");
      var request = buildRequest("GET", resourceUrl);
      request.send();
      return request.onLoadEnd.first.then((event) => fillObject(event.target));
    });
  }

  static fillObject(dom.HttpRequest request) {
    print('fillObject');
    String responseText = request.response;
    List stringJson = JSON.decode(responseText);
  }
}

void main() {
  var json = ['a', 'b', 'c'];
  Xxx.getObjectData(json).then((_) => print('done'));
}

See https://www.dartlang.org/articles/event-loop for more details about async execution.