#javascript #flutter #dart #webapi #dart-js-interop
#javascript #flutter #dart #webapi #dart-js-interop
Вопрос:
Я хотел бы использовать window.showDirectoryPicker()
метод из Dart / Flutter. Использование его из JavaScript, позволяющее пользователю выбирать каталог, а затем перечислять его содержимое, работает следующим образом:
const dirHandle = await window.showDirectoryPicker();
for await (const entry of dirHandle.values()) {
console.log(entry.name);
}
В документах FileSystemDirectoryHandle.values()
говорится, что он возвращает «новый итератор массива, содержащий значения для каждого индекса в FileSystemDirectoryHandle
объекте». В нем конкретно не указано, хотя, похоже, это асинхронный итератор, как того требует перечисление await for
.
Я пытаюсь создать привязки для вызова этого из Dart. Я ожидаю, что моя привязка должна возвращать a 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
являются .
Комментарии:
1. Разработчик Flutter задает вопрос?
2. Мои вклады в основном сосредоточены на инструментах — я не знаю намного больше, чем знаю 🙂
3. Честно говоря, это было очень мотивирующее заявление для таких людей, как я. Я не понял вопроса (даже не могу подумать о том, чтобы соответствовать вашему уровню), но я уверен, что этот вопрос заслуживает того, чтобы его задать. Но опять же, вы, вероятно, были тем, кто мог ответить на это, и вы просто сделали. 1 и большое вам спасибо 🙂
Ответ №1:
Редактировать: кажется, это работает, build_runner serve
но нет build_runner serve --release
. Я отправил запрос, чтобы определить, является ли это ошибкой или это неправильный способ сделать это.
Поняв, что асинхронные итераторы в 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 выше и выводит имена файлов по желанию.