【问题标题】:Exception when javascript awaits a Dart async functionjavascript 等待 Dart 异步函数时的异常
【发布时间】:2022-07-06 05:04:22
【问题描述】:

我有一个 Web 应用程序,我正在为其实现一个可供独立 js 脚本使用的 API。使用推荐的包:js/js.dart 和 @JS 注释,从 js 到 Dart 的调用都可以正常工作,除了对 Dart 函数的异步调用 awaitawait 调用抛出异常或不等待。

我已经编写了一个小示例 VScode 项目,可以轻松重现该问题。

Dart connect 异步函数返回一个 Future,但是当 Future 完成时会抛出异常。这是否与 Dart 返回 Future 但 javascript 期望 Promise 有关?

有很多帖子引用了 javascript 中的 Dart 调用,但我发现使用 async/await 的反向方向(js 到 Dart)很少。我预计 promiseToFuture 和 futureToPromise 函数可能会对这个问题有所启发,但在 js-to-dart 上下文中没有太多信息。关于这个问题的 Dart 文档似乎不存在。

还有一个奇怪的问题可能只是一个症状。使用“webdev serve”,await 调用会抛出异常,但如果它在 try/catch 中被捕获,则 awaits 实际上会等待并返回完成值。使用“webdev build”,等待调用根本不等待。

如果我错过了相关文档,我将非常感谢您指出正确的方向。除此之外,我想听听有关可行解决方案的任何建议!

所有 Dart 代码都在 main.dart 中,构建和测试在:

Dart SDK 2.14.4(稳定版)(2021 年 10 月 13 日星期三 11:11:32 2021 +0200)在“windows_x64”上: VS Code 1.62.3(用户设置) 操作系统:Windows 10 (Windows_NT x64 10.0.19043) Chrome 96.0.4664.45(官方版本)(64 位)

@JS()
library testawait;

import 'dart:async';
import 'dart:core';
import 'package:js/js.dart';

/// main.dart
///
/// This web app is an example of a javascript script await-ing a Dart async
/// function. The Dart async function returns a Future but when the future 
/// is completed an exception is thrown. Is this to do with Dart returning
/// a Future but the javascript expecting a Promise?
/// 
/// The script is triggered by a button (Click me) in the web page (index.html).
///
/// When running with WEBDEV SERVE the awaits respect the Future.delays but throw
/// exceptions and the returns go to the catch.
/// 
/// When running with WEBDEV BUILD the awaits do not delay and the returns go to
/// the next statement.

@JS('connect')
external set _connect(void Function(String host) f);

void main() async {
    _connect = allowInterop(connect);
}

///
/// This causes an exception but the await does wait and the 
/// completion is returned to the catch (with webdev serve):
/// 
///     Uncaught TypeError: T.as is not a function
///     at _Future.new.[_setValue] (future_impl.dart:419)
///
Future<dynamic> connect(String host) async {
    print('main: before connect');
    var completer = Completer<dynamic>();

    // This is just to simulate a connect event being processed
    // elsewhere that completes the completer. This future
    // is not used for anything else.
    Future.delayed(Duration(seconds:2), () {
        print('main: connect done after 3s');
        completer.complete('Future: Connect complete');
    });

    return completer.future;
}

这里是包含 js 脚本的 html;单击“单击我”按钮以触发对 scriptWaits 的调用:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="scaffolded-by" content="https://github.com/dart-lang/sdk">
    <title>testawait</title>
    <script defer src="main.dart.js"></script>
<style>
html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  font-family: 'Roboto', sans-serif;
}

#trigger-div {
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

#trigger-round {
  padding: 40px;
  border-radius: 50%;
  background-color: darksalmon;
}
</style>
</head>

<body>
    <div id='trigger-div'>
        <div id='trigger-round'>
            <input type="button" value="Click me" id="script_trigger" onclick="scriptWaits()"></input>
        </div>
    </div>
    <p>open developer tools console to see results</p>

    <script>
    async function scriptWaits() {
        var reply = '';

        console.log('Script: before calling connect');
        try {
            reply = await connect('host');
            console.log('Script: after calling connect, reply=' + reply);
        } catch(e) {
            reply = e;
            console.log('Script: catch connect wait, ' + reply);    
        }
    }
    </script>
</body>
</html>

和 pubspec.yaml:

name: testawait
description: Testing javascript await a Dart function
version: 1.0.0

environment:
  sdk: '>=2.14.4 <3.0.0'

dependencies:
  http: ^0.13.3

dev_dependencies:
  build_runner: ^2.1.2
  build_web_compilers: ^3.2.1
  js: ^0.6.3
  lints: ^1.0.0

【问题讨论】:

    标签: javascript dart web async-await


    【解决方案1】:

    自 12 月以来你有什么发现吗?

    我发现了这个: dart:js error when calling promiseToFuture - NoSuchMethodError: tried to call a non-function, such as null: 'jsPromise.then'

    但我不确定它是否能回答您的问题。

    【讨论】:

      猜你喜欢
      • 2019-11-29
      • 2023-03-10
      • 2017-12-11
      • 2020-01-14
      • 1970-01-01
      • 2022-01-01
      • 2017-12-07
      • 1970-01-01
      • 2011-03-04
      相关资源
      最近更新 更多