制作一个未来阻止直到它完成

时间:2016-06-08 21:04:43

标签: dart

是否可以阻止返回未来的函数调用?

我的印象就是调用.then()来做,但这不是我在输出中看到的。

print("1");
HttpRequest.getString(url).then((json) {
  print("2");
});
print("3");

我在输出中看到的是:

1
3
2

getString方法没有async允许我await,而then在任何情况下都是异步执行。

  static Future<String> getString(String url,
      {bool withCredentials, void onProgress(ProgressEvent e)}) {
    return request(url, withCredentials: withCredentials,
        onProgress: onProgress).then((HttpRequest xhr) => xhr.responseText);
  }

在第3步等待第2步完成之前,如何在不放置无限循环的情况下使其阻塞(不是因为Dart的单线程特性而无论如何它会起作用)?

上面的HttpRequest加载一个config.json文件,用于确定应用程序中所有内容的工作方式,如果配置中的字段请求在config.json文件加载完成之前完成,则会导致错误,所以我需要等到文件完成加载之前我才允许在类的字段上调用getter,或者getter需要等待config.json文件的一次性加载。

更新,这是我在Günter建议使用Completer之后最终做的工作:

@Injectable()
class ConfigService {

    Completer _api = new Completer();
    Completer _version = new Completer();

    ConfigService() {

        String jsonURI =
            "json/config-" + Uri.base.host.replaceAll("\.", "-") + ".json";
        HttpRequest.getString(jsonURI).then((json) {

            var config = JSON.decode(json);
            this._api.complete(config["api"]);
            this._version.complete(config["version"]);

        });
    }

    Future<String> get api {
        return this._api.future;
    }

    Future<String> get version {
        return this._version.future;
    }

}

我在哪里使用ConfigService

 @override
 ngAfterContentInit() async {

   var api = await config.api;
   var version = await config.version;

   print(api);
   print(version);

 } 

现在我得到了类似阻塞的功能而没有实际阻止。

3 个答案:

答案 0 :(得分:3)

我不确定我理解你想要实现的目标,但在我看来你想要这样做:

myFunction() async {
  print("1");
  final json = await HttpRequest.getString(url);
  print("2");
  print("3");
}

答案 1 :(得分:3)

在异步代码完成之前,无法阻止执行。您可以做的是后续代码,以便在异步代码完成之前不执行它。

链接的一种方式是then

print("1");
HttpRequest.getString(url) // async call that returns a `Future`
.then((json) { // uses the `Future` to chain `(json) { print("2"); }`
  print("2");
});
print("3"); // not chained and therefore executed before the `Future` of `getString()` completes.

异步调用只是为后续执行调度代码。它将被添加到事件队列中,当处理它之前的任务时,它本身将被执行。在安排异步呼叫后,同步代码`print(&#34; 3&#34;)将继续。

在您的情况下,HttpRequest.getString()计划对您的服务器的调用,并将(json) { print("2")注册为当服务器的响应到达时要调用的回调。应用程序的进一步执行不会停止,直到响应到来并且无法实现这一点。相反,会发生同步代码继续执行(print("3"))。 如果您当前执行的同步代码到达其结尾,则以相同的方式处理下一个计划任务。

then()安排在(json) { print("2"); }完成后执行的代码getString()

<强> AWAIT

asyncawait只是让异步代码看起来更像是同步代码,但除此之外它们完全相同,并且会被翻译成xxx.then((y) { ... })

答案 2 :(得分:2)

仅在消费者功能中需要

async语句。换句话说,生产者函数不需要async,他们只需要返回Future

你应该能够做到这一点:

Future consumerFunc() async {
  print("1");

  var response = await HttpRequest.getString(url);

  print("2");

  print("3");
}

它应该结果:

1
2
3

注意:await替换then方法