Итак, сигнатура для аргумента слушателя этой функции observe
в mobx:
listener: (change: IMapChange<K, T>) => void,
Соответствующий бит - это тип возвращаемого значения void
, который указывает, что функция должна быть толькоспособен возвращать undefined
(или неявно только возвращать undefined
, не имея оператора return).
Асинхронные функции всегда возвращают Promise
.Механизм того, как выполняется преобразование async / await и как выглядит результирующий код, хорошо объяснен в спецификации , но достаточно сказать, что ваш код фактически заменяется кодом, который всегда будет возвращать Promise
.
Короткий ответ - просто не передавать асинхронную функцию там, где ее не ожидают.Вот некоторые варианты:
- Переработать функцию, чтобы просто вызвать
then
вместо того, чтобы полагаться на await
.Возможно, самый чистый вариант в этом случае. - Превратите вашу асинхронную функцию во IIFE:
((...args) => { (async (...) {...})(...args) }
- Повторно введите вашу функцию, набрав
any
: ((myListener): any): (MyArgTypes) => void)
(несделать это) - Использовать комментарий
$FlowFixMe
(не делайте этого тоже)
Итак, почему это работает?
Потому что mobx ожидает функцию, которая возвращает только void
, потому что она не собирается ничего делать с любым возвращаемым значением.Он не запрашивает возвращаемое значение, потому что не собирается использовать его.Ваше возвращаемое значение, Promise
, просто отбрасывается mobx.Таким образом, он продолжит работать так же, как и всегда, несмотря на эту ошибку типа.
Почему MOBX не может просто ввести возвращаемое значение как any
?В конце концов, mobx не волнует, что вы возвращаете.
Потому что это было бы плохим дизайном API и внесло бы опасную скользкость при наборе текста.API нужен надежный, разумный контракт.Что если пользователь передаст observe
a listener
, который вернул результат, потому что он ошибочно полагал, что mobx действительно сделает что-то с этим результатом?Или что, если пользователь, например, передал функцию более высокого порядка вместо возвращаемого значения этой функции более высокого порядка?Обе эти ошибки не будут обнаружены менее строгим типом в этой позиции.
Почему асинхронная функция всегда возвращает Promise
, даже если я все равно ее просто отбрасываю?
Хотя возвращение Promise
в зависимости от использования может быть записано в спецификации , или, возможно, передать какую-то опцию, чтобы не возвращать Promise
, вполне вероятно, чтов результате сложился с очень небольшим вознаграждением.Цель спецификации async / await - получить максимально возможную полезность, не добавляя слишком много сложности.Многие, но не все, асинхронные функции используются в сильно асинхронных кодовых базах, где возвращение Promise
будет лучшей идеей, чем нет.Кроме того, после того, как функция была объявлена асинхронной, невозможно безопасно возвращать значение из другого, кроме как асинхронным способом (Promise
), без каких-либо копаний в теле функции и попытки определить использование.