How to make an asynchronous Dart call synchronous?

前端 未结 8 1543
心在旅途
心在旅途 2020-12-14 16:39

I\'m on the way to evaluate Dart for a German company by porting various Java programs to Dart and compare and analyze the results. In the browser Dart wins hands down. For

相关标签:
8条回答
  • 2020-12-14 17:12

    Dart is inherently async. Trying to avoid asynchronity won't work out. There are sync versions of some API calls for example in dart:io and in some situations it might seem simpler to use them instead but because there aren't sync versions for all methods/functions you can't avoid async entirely.

    With the recent introduction of the async/await feature programming async become much simpler and the code looks almost like sync code (but it isn't).

    If a call went async it stays async. As far as I know there is nothing you can do about it.

    0 讨论(0)
  • 2020-12-14 17:13

    /*Since the Await statement can be used in only asynchronous methods. Then we do two methods.I thinking first we call the async method and then we constantly query the null result for the non-async method. Then we get a synchronized model. In this way, we will wait for the answer in the non-async method. Such a method comes to my mind. But as far as I can see, there is no escape from the async working model in flutter dart language. Need to get used to it.It may be unprofessional, but I wanted to share the solution that came to my mind. hope it helps.

     Stock resultStockQueryByBarcodeAsync;
      bool waitStockQueryByBarcodeAsyncCompleted = false;
    
      Stock WaitStockQueryByBarcodeAsync(String barcode, int timeOut) {
        CallStockQueryByBarcodeAsync(barcode);
        var startTime = new DateTime.now();
        while (!waitStockQueryByBarcodeAsyncCompleted) {
          Duration difference = DateTime.now().difference(startTime);
          if (difference.inMilliseconds > timeOut) {
            throw TimeoutException("Timeout Exceeded");
          }
          //we must scope time. Because it can be enter endless loop.
        }
        return resultStockQueryByBarcodeAsync;
      }
    
      void CallStockQueryByBarcodeAsync(String barcode) async {
        waitStockQueryByBarcodeAsyncCompleted = false;
        resultStockQueryByBarcodeAsync = null;
        var stock = await StockQueryByBarcodeAsync(barcode);/*your target async method*/
        waitStockQueryByBarcodeAsyncCompleted = true;
        resultStockQueryByBarcodeAsync = stock;
      }
    
    0 讨论(0)
  • 2020-12-14 17:14

    I came here to find an answer but figured out a way, it's as below and works.

    Future<dynamic> lastCallFuture;
    
    Future<T> myAsyncFunction<T>(T value) async {
      if(lastCallFuture != null) {
        await lastCallFuture;
      }
      return lastCallFuture = _myAsyncFunction(value);
    }
    
    Future<T> _myAsyncFunction<T>(T value) async => value;
    

    You're welcome.

    0 讨论(0)
  • 2020-12-14 17:23

    The resync function cannot be implemented in Dart's current execution model.

    Asynchronous execution is contagious. A synchronous function must return before any other asynchronous events can execute, so there is no way to synchronously wait for asynchronous execution.

    Execution in Dart is single-threaded and event based. There is no way for the resync function to block without it also blocking all other execution in the same isolate, so the pending async operations will never happen.

    To block the synchronous execution, and continue executing something else, you need to preserve the entire call stack up to that point, and reinstate it later when the synchronous operations have completed. If you have that functionality, then there are probably better ways to do things than Future and Stream :)

    Also, waiting for "all async execution" isn't well-defined in an event based system. There might be a broadcast Stream emitting events coming in from the network, a periodic timer, or a receive port getting data from another isolate, or some other source of events that you can't wait for because they come from outside the isolate, or event the process. When the current isolate shuts down, it might send a final shut-down message to another isolate, so effectively the "async execution" isn't over until the isolate dies.

    Using the async/await syntax, you won't get synchronous operation, but it will be easier to code the similar asynchronous operation:

    function() async {
      var result = await asyncFunction();
      return result;
    }
    

    It won't wait for async operations that aren't reflected in the Future returned by asyncFunction, but that's the job of asyncFunction to not complete until its operations are complete.

    0 讨论(0)
  • 2020-12-14 17:28

    The only time that you can wrap an async method in a synchronous one is when you don't need to get a return value.

    For example if you want to disable the save button, save results to the server asynchronously and re-enable the save button when the job is done you can write it like this:

    Future<bool> save() async {
      // save changes async here
      return true;
    }
    
    void saveClicked() {
      saveButton.enabled = false;
      save()
        .then((success) => window.alert(success ? 'Saved' : 'Failed'))
        .catchError((e) => window.alert(e))
        .whenComplete(() { saveButton.enabled = true; });
    }
    

    Note that the saveClicked method is fully synchronous, but executes the save method asynchronously.

    Note that if you make saveClicked async, not only do you have to call it using the async pattern, but the entire method body will run asynchronously so the save button will not be disabled when the function returns.

    For completeness the async version of saveClicked looks like this:

    Future<Null> saveClicked() async {
      saveButton.enabled = false;
      try {
        bool success = await save();
        window.alert(success ? 'Saved' : 'Failed');
      }
      catch (e) {
        window.alert(e);
      }
      finally {
        saveButton.enabled = true;
      }
    }
    
    0 讨论(0)
  • 2020-12-14 17:30

    Yes, this is way late, but I think this is a cool feature new people should know about.

    There is a way, but the Dart docs warn against it (and it's somehow "experimental", although the implications aren't really discussed).

    The waitFor command.

    You basically pass in an asynchronous function that returns a Future, an optional timeout parameter, and the waitFor function will return the result.

    For example:

    final int number = waitFor<int>(someAsyncThatReturnsInt);
    
    0 讨论(0)
提交回复
热议问题