【问题标题】:How to map a JavaScript function returning an async iterator in Dart using package:js?如何使用 package:js 在 Dart 中映射返回异步迭代器的 JavaScript 函数?
【发布时间】:2021-04-21 13:31:18
【问题描述】:

我想使用 Dart/Flutter 中的 window.showDirectoryPicker() method。从 JavaScript 中使用它来允许用户选择一个目录,然后列出它的内容,如下所示:

const dirHandle = await window.showDirectoryPicker();
for await (const entry of dirHandle.values()) {
  console.log(entry.name);
}

FileSystemDirectoryHandle.values() 的文档说它返回“一个新的数组迭代器,其中包含FileSystemDirectoryHandle 对象中每个索引的值。”它没有具体说明,尽管它似乎是一个 async 迭代器,因为枚举它需要await for

我正在尝试创建绑定以从 Dart 调用它。我希望我的绑定应该返回Stream<FileSystemHandle>,尽管我找不到任何关于这样做的示例或文档。我已经尝试了很多组合,但这是我现在所拥有的:

@JS()
library js_lib;

import 'dart:html';

import 'package:js/js.dart';
import 'package:js/js_util.dart';

Future<FileSystemDirectoryHandle> showDirectoryPicker() =>
    promiseToFuture(callMethod(window, 'showDirectoryPicker', []));

@JS()
abstract class FileSystemDirectoryHandle extends FileSystemHandle {
  external Stream<FileSystemHandle> values();
}

@JS()
abstract class FileSystemHandle {
  String get name;
}

@JS()
abstract class FileSystemFileHandle extends FileSystemHandle {}

我试着这样称呼它:

final dirHandle = await showDirectoryPicker();
await for (final item in dirHandle.values()) {
  print(item.name);
}

但是这会像错误一样失败:

错误:需要一个“Stream”类型的值,但得到一个“NativeJavaScriptObject”类型的值

我怀疑我可能需要一些东西来将 JS 迭代器转换为 Dart 流(类似于我的 promiseToFuture 调用),尽管我找不到这样做的方法(我也无法添加方法到FileSystemDirectoryHandle 不是external

【问题讨论】:

  • 一个 Flutter 开发者在问一个问题?
  • 我的贡献主要集中在工具方面 - 我不知道的比我知道的要多得多 :-)
  • 说实话,对于像我这样的一些人来说,这是一个非常鼓舞人心的声明。虽然我不明白这个问题(甚至想不出匹配你的水平),但我相信这个问题值得问。但同样,您可能是能够回答它的人,而您刚刚做到了。 +1,非常感谢你:)

标签: javascript flutter dart webapi dart-js-interop


【解决方案1】:

编辑:这似乎适用于build_runner serve,但不适用于build_runner serve --release。我已经提交了an issue 以确定这是一个错误还是这样做的错误方法。


在意识到 JS 中的异步迭代器只是 next() 返回承诺的迭代器之后,我能够编写一个小函数,它只是手动调用该方法并在 async* 函数中产生:

extension FileSystemDirectoryHandleExtensions on FileSystemDirectoryHandle {
  Stream<FileSystemHandle> values() =>
      _asyncIterator<FileSystemHandle>(callMethod(this, 'values', []));
}

Stream<T> _asyncIterator<T>(jsIterator) async* {
  while (true) {
    final next = await promiseToFuture(callMethod(jsIterator, 'next', []));
    if (getProperty(next, 'done')) {
      break;
    }
    yield getProperty(next, 'value');
  }
}

这是使用上面的原始 Dart 代码调用的,并根据需要打印文件名。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-24
    • 2016-07-05
    • 2021-05-20
    • 1970-01-01
    • 2021-08-30
    • 2022-11-16
    • 1970-01-01
    相关资源
    最近更新 更多