Flutter中await调用异步上传函数未等待执行完成的问题
问题原因
await upload()的调用逻辑本身没有问题,bug出在upload函数内部的响应处理环节:
response.stream.transform(utf8.decoder).listen()属于非阻塞的流订阅操作,调用listen注册完回调后,代码不会等待回调执行,会直接向下运行到return createdFileName语句- 此时响应流还未完成数据解析,
createdFileName仍是初始化时的空字符串,函数会直接将空值返回 - 等后续流读取到服务端返回的文件名、执行回调给
createdFileName赋值时,函数早已完成返回,赋值操作无法修改已经返回的结果,最终列表里拿到的全是空值,表现为循环未等待上传完成就进入下一轮迭代。
修复方案
替换非阻塞的listen订阅逻辑,使用await等待响应流完整解析完成后再返回结果,修复后的upload函数代码如下:
Future<String> upload(File imageFile) async { var stream = http.ByteStream(DelegatingStream.typed(imageFile.openRead())); var length = await imageFile.length(); var uri = Uri.parse("http://localhost:8080/upload"); var request = http.MultipartRequest("POST", uri); var multipartFile = http.MultipartFile( 'file', stream, length, filename: basename(imageFile.path) ); request.files.add(multipartFile); var response = await request.send(); print(response.statusCode); // 等待响应流完整解码拼接,拿到服务端返回的文件名 final createdFileName = await response.stream.transform(utf8.decoder).join(); print(createdFileName); return createdFileName; }
原有循环调用的代码无需修改,修复后循环会按顺序等待每个文件上传完成、拿到正确的文件名后再进入下一轮迭代,createdFileNames列表就能得到正确的返回值。
注:使用
join()可以自动拼接响应流的所有分片内容,适配服务端分块返回响应的场景,避免出现文件名截断的问题。
内容的提问来源于stack exchange,提问作者jansemrau
相关产品推荐
相关产品推荐

