【问题标题】:Have an issue when calling a callback function from finally block从 finally 块调用回调函数时出现问题
【发布时间】:2022-01-19 06:24:46
【问题描述】:

从异步函数下的 finally 块调用回调函数时遇到问题。此问题仅在将 Web 发布版本部署到 Web 服务器时发生。

要部署网络,我会执行以下操作。

  1. 使用以下方法构建 Web 项目:flutter build web
  2. 将 Web 发布文件夹部署到真实服务器
  3. 使用 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&lt;String, dynamic&gt;? 而不是 var
  • @jamesdlin 谢谢。使用“Map?_resp;”没有帮助。
  • 第二个建议是正确键入变量(并避免至少需要一些强制转换)。初始化变量的第一个建议有帮助吗?
  • 我不明白。正如我所说,使用Map&lt;String, dynamic&gt;? _resp; 不应该解决您的问题。 初始化_resp(例如var _resp = &lt;String, dynamic&gt;{};)应该会有所帮助,因为这会阻止callback被未初始化的参数调用。
  • 在我的示例代码中,代码行_resp = (json.decode(response.body) as Map&lt;String, dynamic&gt;)被正常调用,然后_resp在finally块之前被初始化。正如您在我发布的日志中看到的那样,_resp json 已经打印出来:{success: true}。但是,访问地图成员resp["success"] 会导致错误。那是我觉得很奇怪的事情。

标签: flutter dart flutter-web


【解决方案1】:

@jamesdlin 你是对的。由Map&lt;String, dynamic&gt; _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
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    • 2021-08-22
    • 1970-01-01
    • 2021-02-13
    • 2017-07-17
    相关资源
    最近更新 更多