Bloc: Event not firing inside a for loop

Created on 17 Jun 2020  ·  12Comments  ·  Source: felangel/bloc

So I am not sure if this is a dart or bloc thing.
I have this:

for(final url in urlList) {
  final request = await http.get(url);
   await file.writeAsBytes(request.bodyBytes, mode: FileMode.writeOnlyAppend);
  myCallback.call();
}

My Bloc:

if(event is DownloadFileRequested) {
  await repository.downloadFile(onDownloadPercentageChanged: (percentage) => add(FileDownloadPercentageChanged(percentage));
} else if(event is FileDownloadPercentageChanged) {
  print(“Plz Change”);
  yield const VideoDownloading(event.percentage);
}

The callback is supposed to call the FileDownloadPercentageChanged event but the event is not firing. It fires right after the for loop ends.

Much thanks everyone!

EDIT: it won’t even fire outside the for loop. It will only fire when the function ends

question

Most helpful comment

@RollyPeres YES IT IS WORKING!!!!!! Rolly rolly rolly I love you man!! It was that await in the bloc causing the error lol! Thank you very very much! I will close this now! Don’t want to piss Felix 😂

All 12 comments

Hi @DeadlyMissile, welcome back 👋

That's too little code to tell what's really going on. It appears your callback should be invoked right after data is written to the file.
If what you're looking for is to get updates on the download percentage of your file I'd recommend having a look at https://github.com/felangel/bloc/issues/1218#issuecomment-634537394 for a quick overview of achieving that using dio.

If you're trying to achieve something different please give more details and attach a minimal sample repo illustrating your issues. 👍

Hi @RollyPeres ! Sorry for the late reply!

I got my code from that git comment haha. The callback should indeed fire after the it is done writing to the file but it doesn’t. Instead they start firing when the function ends. Maybe they only work inside streams? Because it works ok on my other stream function

And thanks again Rolly :D

If you can't get it to work feel free to share a minimal reproduction example repo and I'm happy to have a look 👍

@RollyPeres I found the issue! The moment I have an “await” keyword inside the function the callback will fire after the whole function ends. When I remove await then it works fine. However I still need await to await for my http get requests

Not sure what exactly you want to achieve but you can surely chain .then((_) => callback.call()) or .whenComplete(callback) if that helps your use case.

@RollyPeres All I want to do is loop through a list of urls, do http.get on each one of them and fire a callback. Then save their bytes to a file

Have you tried

for(final url in urlList) {
  final request = await http.get(url).then((result) {
  myCallback.call();
  return result;
});
   await file.writeAsBytes(request.bodyBytes, mode: FileMode.writeOnlyAppend);
}

?

@RollyPeres The getter bodyBytes was called on null :( But yeah still callback gets fired at the end of the function

My bad, updated the example. If you still have issues with your implementation please create a minimal reproduction example that I can run locally. It would be easier to help you if I can see your full approach.

My Bloc:

if(event is DownloadFileRequested) {
  await repository.downloadFile(onDownloadPercentageChanged: (percentage) => add(FileDownloadPercentageChanged(percentage));
} else if(event is FileDownloadPercentageChanged) {
  yield const VideoDownloading(event.percentage);
}

This is the script:

typedef DownloadPercentageChanged = void Function(double percentage);

Future downloadFile(
    DownloadPercentageChanged onDownloadPercentageChanged,
  ) {
    final request = await http.get(url);
    final response = request.body.split(“/n”);
    for(final urls in response) {
       final req = await http.get(urls);
       await file.writeAsBytes(req.bodyBytes, mode: FileMode.writeOnlyAppend);
       //Need to call my onDownloadPercentChanged here
    }
  }

Thanks again @RollyPeres !

I'm not sure how you're running your code since that won't even compile since you're using await in a non-async method.

Here's a gist accomplishing what you want although to me it doesn't make sense since that won't give you the download percentage; at best you'll get video no that just finished downloading.
Your callback wasn't firing because you were awaiting downloadFile in your bloc and until everything finishes it won't execute your callbacks. Solution is to remove await and base your error handling on chaining a catchError.

A thing to remember is to not inject the client directly into your bloc but through a repository.

@RollyPeres YES IT IS WORKING!!!!!! Rolly rolly rolly I love you man!! It was that await in the bloc causing the error lol! Thank you very very much! I will close this now! Don’t want to piss Felix 😂

Was this page helpful?
0 / 5 - 0 ratings