打字稿:需要在全局范围内声明一个从异步函数读取的常量

时间:2018-10-15 15:18:52

标签: javascript typescript asynchronous scope const

在这里有一个新手问题。我需要在我的Typescript文件的顶层声明常量,因此下面的所有功能都可以使用它。问题是我需要分配给该常量的值由异步函数返回,而这就是我遇到的问题。不能从顶层调用异步函数-我可以执行类似的操作,但是在这种情况下,常量不再位于顶层,并且不能被其他函数访问。

(async () => {
    const myConst = await asyncFunction(params);
})(); 

另一种选择是使用let而不是const,就像这样,但是我宁愿在上面使用const

let myConst;
(async () => {
    myConst = await asyncFunction(params);
})();

你能告诉我吗?有什么办法解决这个问题,以便我可以为全局范围声明const并根据异步函数为其分配一个值?

非常感谢:)

3 个答案:

答案 0 :(得分:4)

在顶级变量中使用异步结果是有问题的,因为无法静态保证模块中的函数尝试读取该值时结果将准备就绪。在我看来,执行此操作的正确和安全的方法是将诺言赋给顶级变量,并使任何读取值await的函数成为结果:

const myConst = asyncFunction(params);

async function example() {
  doStuff(await myConst);
}

但是,如果要在顶级变量中获取异步结果很重要,并且您可以通过某种方法来保证该值在读取之前就已经准备好,那么我将使用您的let赋值。在这种情况下,我认为没有什么好方法可以使该变量成为const

答案 1 :(得分:2)

问题在于,由于提供值的操作是异步的,因此模块中的其他函数可能会在设置值之前尝试使用变量/常量。因此,最好避免这样做,也许可以按照Jesse Hallett的建议进行操作,并强制模块中的其他函数使用promise。

如果您无法避免这种情况,并且您确定在异步操作获取值返回之前肯定不会调用这些函数,请使用let选项用null初始化变量或其他一些标志值,并检查在准备好并抛出它们之前应该不会调用的函数中的标志值。例如:

let myConst = null; // null or some other value that isn't valid for this
(async () => {
    try {
        myConst = await asyncFunction(params);
    } catch (e) {
        // Handle the fact the async function failed -- don't skip this!
    }
})();

function assumeMyConst() {
    if (myConst === null) {
        throw new Error("State error: myConst not available yet");
    }
}

function foo() {
    assumeMyConst();
    // ...
}

但同样,请尽可能避免使用它。


旁注:请注意该async IIFE中的错误检查。不要跳过错误检查。 :-)

答案 2 :(得分:1)

由于myConstasync代码完成后获得其值,因此它是Promise类型的。因此,您的声明应该非常简单:

declare const myConst: Promise<any> // or type of the value instead of any

在任何地方使用它:

myConst.then((v) => console.log(v))

P.S。我的个人建议是尽可能使用模块(导入/导出)。全局变量是代码的味道。