“观察”功能中的异步功能

时间:2019-02-27 12:27:11

标签: javascript asynchronous flowtype mobx

好吧,我有以下代码似乎可以正常运行:

observe(
    store, "user",
    async (data: {oldValue: ?UserTy, newValue: ?UserTy}) => {
        const {oldValue: previousUser, newValue: newUser} = data;

        this.entries = [];
        this.confirmed_entries = [];
        this.paid_entries = [];
        if (newUser) {
            const clear = !!previousUser;
            await this.reloadEntries(clear);
        }
        this.last_reload = new Date();
    }
);

在用户更改(登录/注销)后,哪个将从数据库中重新加载当前用户的“条目”。

现在,我将流量添加到混合中,突然出现以下错误:

  

错误:(47,64)无法通过绑定到observe的异步函数调用listener,因为返回中的Promise [1]与未定义的[2]不兼容值。

看着mobx.js.flow,我确实可以看到它总是接受一个简单的函数,返回void。有关此文件的文档为silent。那么观察者可以在其中接受一个Promise(异步)功能吗? -这是打字中的“错误”吗?
还是我使用观察者是错误的,我只是“幸运”地指出函数最终会执行吗?

如果无法做到这一点,重写它的最佳方法是什么?最后,我需要调用this.reloadEntries(),它会在更改用户后返回一个Promise /对该服务器进行调用。

1 个答案:

答案 0 :(得分:0)

因此,mobx中此observe函数的侦听器参数的签名为:

listener: (change: IMapChange<K, T>) => void,

相关的位是返回类型void,它指示该函数应该只能返回undefined(或者隐含地,由于没有return语句而仅返回undefined)。

异步函数始终返回Promisethe spec中很好地解释了如何执行异步/等待转换以及生成的代码的机制,但足以说明您的代码已被始终返回{{1}的代码有效地替换了}。

最简单的答案是不传递不期望使用的异步函数。以下是一些选项:

  1. 重做该函数以仅调用Promise而不是依赖then。在这种情况下,可能是最干净的选择。
  2. 将您的异步函数转换为IIFE:await
  3. 通过输入((...args) => { (async (...) {...})(...args) }any(不要这样做)重新输入函数
  4. 使用((myListener): any): (MyArgTypes) => void)注释(也不要这样做)

那么,为什么它起作用?

因为mobx期望一个仅返回$FlowFixMe的函数,因为它不会对任何返回值执行任何操作。它不要求返回值,因为它不会使用一个。您的返回值void被mobx丢弃。因此,尽管出现此类型错误,它仍将像往常一样继续工作。

为什么mobx不只是将返回值键入为Promise?毕竟,mobx不在乎您返回的内容。

因为这将是错误的API设计,并在打字时引入危险的滑移性。 API需要可靠,合理的合同。如果用户由于误解mobx实际上会对该结果,而让用户传递anyobserve来返回结果该怎么办?或者,例如,如果用户传递了一个高阶函数而不是那个高阶函数的返回值,该怎么办?在这种情况下,这两种错误都不会被不太严格的类型捕获。

为什么即使我还是要丢弃它,异步函数也总是返回listener

虽然仅根据使用情况可以返回Promise ,或者将某种选项传递给不返回Promise的规范,结果可能是由于很少的回报而使复杂性迅速增加。异步/等待规范的目标是在不增加过多复杂性的情况下获得最大的效用。高度异步的代码库中使用了许多(但不是全部)异步函数,在这些异步代码库中,返回Promise可能是一个更好的主意。此外,一旦函数被声明为异步,就无法以异步方式(Promise)安全地从其他函数返回值,而无需以某种方式深入了解函数主体并尝试确定用法。