Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flutter Web buffering streamed/chunked data #593

Closed
phishphen opened this issue Jul 12, 2021 · 3 comments
Closed

Flutter Web buffering streamed/chunked data #593

phishphen opened this issue Jul 12, 2021 · 3 comments

Comments

@phishphen
Copy link

I have a local server that will emit numbers 1-10 back to the app when hit. On Flutter android and ios devices, the app procceses each data chunk as they come and it works as expected. On the Flutter Web version, the data is buffered until the end of the stream AND THEN processes the data...how do I get Flutter Web to process each data chunk as they come and not buffer the stream, like the android and ios versions do?

sample code:

import 'package:http/http.dart' as http;

void _postIt() async {
syncingz = true;
http.Request request = http.Request('POST', url);
http.StreamedResponse response = await http.Client().send(request); // make a stream request
streamedRes = response.stream.listen( (value) { // listen to the stream
print(utf8.decode(value)); // print out each yield return as it arrives...in sequence
res = utf8.decode(value);
}
setState(() {}); // update flutter ui with each data chunk received
},
);
await streamedRes.asFuture();
print('all done');
streamedRes.cancel();
syncingz = false;
setState((){});
}

android ios results:
1
2
3
4...
all done

flutter web results:
12345678910
all done

@natebosch
Copy link
Member

This is mentioned as a limitation in the docs for BrowserClient.

/// [BaseRequest.followRedirects], and [BaseRequest.maxRedirects] fields. It is
/// also unable to stream requests or responses; a request will only be sent and
/// a response will only be returned once all the data is available.

Streaming does not work for the browser client because it uses XmlHttpRequest which has the same limitation. We were previously unable to migrate to fetch because it would limit browser support too much, but that may be something we can revisit. #595

@natebosch
Copy link
Member

Please follow #595 for updates, but I don't expect anything in the short term.

@phishphen
Copy link
Author

Thanks for the reply. I think i might have found a work around using dart:html.

void _postIt() async {
    syncingz = true;
    Map<String, String> body = {
        'test': 'tegffgst'
      };

    // This is for Flutter Web
    final httpReq = HttpRequest();
    String alreadyReceived = '';
    var parts = [];
    body.forEach((key, value) {
      parts.add('${Uri.encodeQueryComponent(key)}='
          '${Uri.encodeQueryComponent(value)}');
    });
    var data = parts.join('&');

    httpReq
      ..open('POST', 'http://localhost:8080/10')
      ..setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
      ..onProgress.listen((event) {   // 3 characters is the min before it registers as an event...less than 3 characters, its gonna return blank until above 3.
        res = httpReq.responseText.replaceAll(RegExp(alreadyReceived), '');
        print(res);
        alreadyReceived = httpReq.responseText;
        setState(() {});
      })
      ..onLoadEnd.listen((event) {
        print('all done');
        syncingz = false;
        setState((){});
      })
      ..onError.listen((event) {
        
      })
      ..send(data);
    await httpReq.onLoadEnd.isEmpty;  // this is to block the code from going forward until httpReq is done
    print('this is the END');
}

Returned results:
1
2
3...
all done
this is the END

This code would need to be commented out, though, before compiling for android/ios as it will throw errors. The original code from my first question works fine for android/ios

fusion44 added a commit to fusion44/blitz_gui that referenced this issue Dec 30, 2021
A workaround was necessary because the dart:html BrowserClient doesn't
directly support streaming repsonses:
flutter/flutter#86199
flutter/flutter#43343

Workaround idea:
dart-lang/http#593 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants