【问题标题】:Asynchronus Intellisense in Visual Studio Code | NodeJSVisual Studio Code 中的异步智能感知节点JS
【发布时间】:2021-06-10 23:55:54
【问题描述】:

我经常编写异步模块,由于它们的异步特性,我会在一些初始化代码期间请求、解析并分配这些模块。例如:

var asynchronousModule;


function doSomethingUsingMyLoadedModule() {
    // Ideally intellisense would be able to do its thing for asynchronousModule right here
    asynchronousModule._doSomething();
}


// initializer
(async () => {
    asynchrousModule = await require('my-custom-async-module');
})();

但是,由于 asynchronousModule 直到 doSomethingUsingMyLoadedModule 函数声明后才被分配,智能感知无法在该函数内自动完成/自动填充 asynchronousModule

所以我想知道是否有一种方法可以明确告诉智能感知过早在声明时为我们的变量赋值,使用 inline-cmets 或类似的方法。例如,第一行是这样的:

var asynchronousModule; // vsc-intellisense assign-async-import my-custom-async-module

那太棒了,但可能是一厢情愿。但是,也许还有其他方法可以将智能感知用于异步模块,而不必将我的整个文件包装在异步函数中?我的意思是把我的代码重写成这样的:

(async () => {
    const asynchrousModule = await require('my-custom-async-module');

    function doSomethingUsingMyLoadedModule() {
        asynchrousModule._doSomething();
    }
})();

虽然这可以让智能感知工作,而且在这个例子中看起来确实不错,但我真的不喜欢用标签覆盖整个文件的内容,尤其是当文件变大时,所以这不是我理想的解决方案。

【问题讨论】:

  • 为什么需要await require('my-custom-async-module');await有什么用
  • @rioV8 该模块是异步的,因此它返回一个承诺。因此,我需要等待才能解决承诺。作为一个示例用例,也许我的模块建立并保留了一个数据库连接,这样我就可以在多个文件中重用这个相同的连接。因为建立一个 DB 连接是异步的,所以该模块会导出一个 Promise,它将解析到该 DB 连接中。因此,通过 await 或通过 promise.then 解决 promise 是获取模块实际有用部分的必要条件。
  • _doSomething() 函数中处理promise。模块应该写成导出不包含 Promise。加载模块时不要建立数据库连接,而是在需要它的函数内部,缓存数据库连接的结果
  • @rioV8 这可行,但我认为这不是最佳选择。假设我的模块现在是同步的,但它的唯一目的是通过其唯一的方法_doSomething() 公开和缓存共享数据库连接。尽管连接在第一次调用后被缓存,_doSomething() 仍然会在后续调用中返回一个承诺(否则我将不断地检查它的返回类型)。尽管等待单个已解决的 Promise 的开销可以忽略不计,但现在想象一下以这种方式构建的一系列依赖模块,每个模块都在等待下一个已解决的 Promise。

标签: javascript node.js asynchronous visual-studio-code intellisense


【解决方案1】:

试试这个

const asynchrousModule = require('my-custom-async-module');

function doSomethingUsingMyLoadedModule() {
    asynchrousModule._doSomething();
}

【讨论】:

  • 不幸的是,正如我在回复您对我的 OP 的评论中解释的那样,这不起作用,因为它是一个异步模块,这意味着该模块返回一个承诺,该承诺稍后将使用我们的 _doSomething 解析为一个对象方法。
【解决方案2】:

当我第一次问这个问题时,我是一个天真的开发人员,我不了解在我的编辑器中为 IntelliSense 编写 JSDoc 式语法时实际使用了多少 TypeScript。但现在,作为一个聪明得多的开发人员,一个月后发生变化,我对此有了答案。

请注意,我不一定用承诺覆盖模块的导出对象是个好主意,但过去这样做对我有用,并且至少我可以使用以下内容为遗留代码提供准确的 IntelliSense:

/**
 * @template T
 * @typedef  {T extends Promise<infer Value> ? Value : T} PromiseValue
 */

/** @type {PromiseValue<import('my-custom-async-module')>} */
var asynchronousModule;

@typedef 标签声明了 PromiseValue 类型,我们使用它来提取承诺解析的内容。然后使用@type 标记,我们导入异步模块并将其包装在我们的PromiseValue 实用程序中以提取其解析对象。

【讨论】:

    猜你喜欢
    • 2016-04-12
    • 2021-01-07
    • 2016-02-27
    • 2018-02-24
    • 2017-05-28
    • 1970-01-01
    • 2016-06-27
    • 2018-09-05
    • 2021-03-03
    相关资源
    最近更新 更多