Как вернуть значение функции из внутреннего слушателя функции/потока?

Я писал функцию в dart, которая удаляла бы объект из индексированной БД на стороне браузера, когда обнаружил, что должен возвращать значение внешней функции из внутренней функции:

Future<bool> delete() {
    Transaction tx = db.transactionStore(storeName, "readwrite");
    ObjectStore os = tx.objectStore(storeName);
    os.delete(_key); // returns blank future, modifies tx

    // This is not correct, but shows the idea:
    if (tx.onComplete) {return true;}
    if (tx.onError) {return false;}
}

Эта функция является методом класса, который я использую для сохранения и загрузки в индексированную базу данных. Я хочу, чтобы эта функция возвращала true или false или объект Future, содержащий то же самое, когда операция удаления завершается успешно или неудачно. Однако узким местом является оператор os.delete(_key);: он возвращает будущее, но фактический успех или неудача операции удаления обеспечивается tx.onComplete и tx.onError. Оба эти объекта являются потоками, поэтому мне нужно создать анонимные функции, которые обрабатывают от них события:

tx.onComplete.listen((e){
    return_to_outer_function(true);
});
tx.onError.listen((e){
    return_to_outer_function(false);
});
return_to_outer_function(bool) {
    return bool; // doesn't work
}

Как видите, когда я создаю анонимные функции, оператор return больше не завершает метод, а завершает внутреннюю функцию. Я мог бы заставить внутренние функции вызывать другие функции, но тогда эти другие функции имеют собственные операторы возврата, которые не возвращают результат всему методу.

Я пробовал устанавливать временные переменные и периодически их проверять, но это очень неэлегантное решение, которое я не хочу использовать не только для потенциальных ошибок, но и потому, что оно перегрузило бы однопоточный цикл обработки событий.

Можно ли вернуть значение внешней функции из внутренней функции? Или есть другой, лучший способ получить значение по наличию или отсутствию событий из набора потоков? Или есть другой способ использования IndexedDB, который позволит избежать этой проблемы?


person Skyler827    schedule 06.07.2014    source источник


Ответы (1)


Вы можете использовать Completer для этого.

Future<bool> delete() {
  Completer completer = new Completer();
  Transaction tx = db.transactionStore(storeName, "readwrite");
  ObjectStore os = tx.objectStore(storeName);

  tx.onError.first((e){
    //return_to_outer_function(false);
    completer.complete(false);
  });
  tx.onComplete.first(bool) {
    //return bool; // doesn't work
    completer.complete(true)
  }
  os.delete(_key); // register listeners and then do delete to be on the save side

  return completer.future;
}

затем вы называете это как

delete().then((success) => print('succeeded: $success'));

см. также https://api.dartlang.org/apidocs/channels/be/dartdoc-viewer/dart%3aasync.Completer

person Günter Zöchbauer    schedule 06.07.2014