从 finally 块调用回调函数时出现问题
Posted
技术标签:
【中文标题】从 finally 块调用回调函数时出现问题【英文标题】:Have an issue when calling a callback function from finally block 【发布时间】:2022-01-19 06:24:46 【问题描述】:从异步函数下的 finally 块调用回调函数时遇到问题。此问题仅在将 Web 发布版本部署到 Web 服务器时发生。
要部署网络,我会执行以下操作。
-
使用以下方法构建 Web 项目:flutter build web
将 Web 发布文件夹部署到真实服务器
使用 Chrome 连接到网络:https://192.168.96.102:1443/#/
我的代码如下:
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async
Map<String, dynamic> payload =
"Id": 78912,
"Customer": "Jason Sweet",
"Quantity": 1,
"Price": 18.00
;
print("Doing JSON POST ...");
await request(
"https://reqbin.com/echo/post/json",
payload,
(error, Map<String, dynamic> resp)
print(resp);
print(resp["success"]);
print("xxx");
);
print("JSON POST Done!");
runApp(const MyApp());
class MyApp extends StatelessWidget
// Codes are ommited for simple
Future<void> request(uri, payload, callback) async
var _resp;
int errorCode = -1;
Map<String, String> _headers =
'Content-type': 'application/json'
;
try
http.Response response;
response = await http.post(
Uri.parse(uri),
body: json.encode(payload),
headers: _headers).timeout(const Duration(seconds: 20));
if (response.statusCode == 200 || response.statusCode == 204)
errorCode = 0;
if (response.body != "")
try
_resp = (json.decode(response.body) as Map<String, dynamic>);
catch (_)
try
_resp = (json.decode(response.body) as List<dynamic>);
catch (_)
errorCode = -1;
_resp = .cast<String, dynamic>();
return;
catch (e)
errorCode = -1;
finally
callback(errorCode, _resp); // *** Doubt that invoke "callback" funtion in "finally" block caused issue.
调用以下代码时:
print("Doing JSON POST ...");
await request(
"https://reqbin.com/echo/post/json",
payload,
(error, Map<String, dynamic> resp)
print(resp);
print(resp["success"]); // Crashed at this line
print("xxx");
);
print("JSON POST Done!");
我希望打印以下内容:
Doing JSON POST ...
success: true
true
xxx
POST Done!
但其实输出是这样的:
main.dart.js:15357 Doing JSON POST ...
main.dart.js:1741 Fetch finished loading: GET "https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Me5WZLCzYlKw.ttf".
main.dart.js:15357 success: true
main.dart.js:3671 Uncaught TypeError: Cannot read properties of undefined (reading 'j')
at a_l.$2 (main.dart.js:46822)
at main.dart.js:14958
at ZL.a (main.dart.js:4846)
at ZL.$2 (main.dart.js:26907)
at YQ.$1 (main.dart.js:26901)
at XI.TZ (main.dart.js:27546)
at XI.uA (main.dart.js:27548)
at Wm.$0 (main.dart.js:27163)
at Object.nz (main.dart.js:4957)
at U.hy (main.dart.js:27087)
颤振信息:
flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.8.0, on Microsoft Windows [Version 10.0.19043.1348], locale en-US)
[√] android toolchain - develop for Android devices (Android SDK version 30.0.0)
[√] Chrome - develop for the web
[√] Visual Studio - develop for Windows (Visual Studio Community 2019 16.3.1)
[√] Android Studio (version 2020.3)
[√] VS Code (version 1.63.1)
[√] Connected device (3 available)
• No issues found!
谁能帮我解释一下为什么会出现这个问题?谢谢。
【问题讨论】:
_resp
在执行finally
块时不一定会初始化。此外,您应该将其声明为 Map<String, dynamic>?
而不是 var
。
@jamesdlin 谢谢。使用“MapMap<String, dynamic>? _resp;
不应该解决您的问题。 初始化_resp
(例如var _resp = <String, dynamic>;
)应该会有所帮助,因为这会阻止callback
被未初始化的参数调用。
在我的示例代码中,代码行_resp = (json.decode(response.body) as Map<String, dynamic>)
被正常调用,然后_resp
在finally块之前被初始化。正如您在我发布的日志中看到的那样,_resp
json 已经打印出来:success: true
。但是,访问地图成员resp["success"]
会导致错误。那是我觉得很奇怪的事情。
【参考方案1】:
@jamesdlin 你是对的。由Map<String, dynamic> _resp = ;
初始化_resp 解决了这个问题。但是,我很不清楚为什么如果在 finally 块之外调用“回调”,即使没有初始化 _resp,我也不会遇到问题。以下代码可以正常工作。
Future<void> request(uri, payload, callback) async
var _resp;
int errorCode = -1;
Map<String, String> _headers =
'Content-type': 'application/json'
;
try
// Omitted some codes for simple
// ...
callback(errorCode, _resp); // This calling is OK even when no initializing for _resp
catch (e)
errorCode = -1;
callback(-1, null);
finally
// callback(errorCode, _resp); // Failed if calling in the finally block when no initializing for _resp
【讨论】:
以上是关于从 finally 块调用回调函数时出现问题的主要内容,如果未能解决你的问题,请参考以下文章
在 WASM-Bindgen Rust 中使用鼠标输入事件闭包创建回调时出现闭包调用错误
在 AsyncTask 中使用回调函数时出现 NullpointerException
设计一个函数,它接受不定数量的参数,这是参数都是函数。这些函数都接受一个回调函数作为参数,按照回调函数被调用的顺序返回函数名