使用打字稿在 Firebase Cloud 函数中动态导入类的正确方法是啥?

Posted

技术标签:

【中文标题】使用打字稿在 Firebase Cloud 函数中动态导入类的正确方法是啥?【英文标题】:What is the correct way to dynamically import a class inside of a Firebase Cloud function using typescript?使用打字稿在 Firebase Cloud 函数中动态导入类的正确方法是什么? 【发布时间】:2020-03-12 14:19:33 【问题描述】:

在 Firebase Cloud Function 项目中...

我的src 目录的根目录下有以下打字稿文件,就在我的主要index.ts 文件旁边,该文件导入一个依赖项并导出一个包含2 个方法的类。这个文件的标题是bcrypt.class.ts

import * as bcrypt from 'bcryptjs';

export default class BcryptTool 
  public static hashValue(value: string, rounds: number, callback: (error: Error, hash: string) => void) : void 
      bcrypt.hash(value, rounds, (error:any, hash:any) => 
            callback(error, hash);
      );
  
  public static compare(value: string, dbHash: string, callback: (error: string | null, match: boolean | null) => void) 
    bcrypt.compare(value, dbHash, (err: Error, match: boolean) => 
        if(match) 
            callback(null, true);
         else 
            callback('Invalid value match', null);
        
    );
  

在我的 Firebase Cloud 函数 index.ts 文件中,我导入了这个类并在我的一个函数中调用它的“比较”方法,没有问题,这可以按预期工作:

'use strict';
const express = require('express');
const functions = require('firebase-functions');
const cors = require('cors')( origin: true );

const admin = require('firebase-admin');
admin.initializeApp();

const api = express();

import BcryptTool from './bcrypt.class'; // <-- i import the class here

// and use it in a function

api.use(cors);
api.post('/credentials', async (request: any, response: any) => 

   BcryptTool.compare(...) // <--- calls to this method succeed without issue

);

问题

我的应用程序包含许多函数,但我只需要上面提到的类在其中一个,所以为了优化我所有其他函数的冷启动时间,我尝试在需要的函数中动态导入这个类它而不是如上所述将其导入全局范围。这不起作用,我不知道为什么:

'use strict';
const express = require('express');
const functions = require('firebase-functions');
const cors = require('cors')( origin: true );

const admin = require('firebase-admin');
admin.initializeApp();

const api = express();

api.use(cors);
api.post('/credentials', async (request: any, response: any) => 

   const BcryptTool = await import('./bcrypt.class'); // <-- when i attempt to import here instead

   BcryptTool.compare(...) // <--- subsequent calls to this method fail

   // Additionally, VS Code hinting displays a warning: Property 'compare' does not exist on type 'typeof import('FULL/PATH/TO/MY/bcrypt.class')' 

);

我的课程没有正确编写或导出吗?

我没有在我的云函数中正确导入类吗?

【问题讨论】:

【参考方案1】:

***导入 (import BcryptTool from './bcrypt.class';) 将自动从 bcrypt.class 模块导入 default 导出。但是,当使用 import 语句作为函数时(所谓的“动态导入”),它将导入 模块 本身,而不是默认导出。

您可以看到console.log(BcryptTool) 两个导入时的区别:

import BcryptTool from './bcrypt.class' 将显示 default: [Function: BcryptTool] hashValue: [Function], compare: [Function] const BcryptTool = await require('bcrypt.class') 将显示 [Function: BcryptTool] hashValue: [Function], compare: [Function]

您注意到第一个 console.log 中的default了吗?这表明您导入了模块,而不是默认模块。

现在实际上import BcryptTool from './bcrypt.class' 语法是执行import default as BcryptTool from './bcrypt.class' 的语法糖。如果您将这些知识应用于动态导入,您可以这样做:

const BcryptToolModule = await import('./bcrypt.class');
BcryptToolModule.default.compare(...);

或者用更简洁的语法:

const  default: BcryptTool  = await import('./bcrypt.class');
BcryptTool.compare(...);

【讨论】:

优秀的细节,每个示例都完美运行。考虑到我作为默认功能导出,这里有什么优点或缺点吗?我应该只导出没有“默认”表示法的类吗? 我认为您的默认导出很好,据我所知,这只是语法上的不同。

以上是关于使用打字稿在 Firebase Cloud 函数中动态导入类的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

为啥打字稿在实现抽象函数时忽略严格的空检查?

打字稿在元组联合中缩小范围

使用打字稿在reduce方法中使用扩展语法进行解构

如何使用打字稿在reactjs中传递数据

如何使用打字稿在表格的单元格中动态插入锚标记?

打字稿在vscode中找不到名称'test'