Javascript 如何与消费应用程序的输入共享对象实例?

Javascript 如何与消费应用程序的输入共享对象实例?,javascript,ecmascript-6,Javascript,Ecmascript 6,现在,我有一个大的单片应用程序。但是,我的目标是提取一些代码,将其放在一个单独的git存储库中,并制作一个单独的npm包。然后这个包将被以前的单片代码库使用。同样的软件包最终也会在其他应用程序中使用 作为此最终共享代码一部分的ES6类之一采用了两个构造函数参数: export class Entitlement { //stuff constructor (entitlementsAliasMap: EntitlementsAliasMap, autoEnable: AutoEnab

现在,我有一个大的单片应用程序。但是,我的目标是提取一些代码,将其放在一个单独的git存储库中,并制作一个单独的npm包。然后这个包将被以前的单片代码库使用。同样的软件包最终也会在其他应用程序中使用

作为此最终共享代码一部分的ES6类之一采用了两个构造函数参数:

export class Entitlement {
   //stuff
   constructor (entitlementsAliasMap: EntitlementsAliasMap, autoEnable: AutoEnableMap) {
     //constructor stuff
   }
   //lots more stuff
}
这两个构造函数参数应该来自共享代码的消费应用程序。一旦提供了这些参数,我就需要实际实例化这个类。我想通过共享代码集中的ES6导入与其他代码共享创建的类的实例

我认为一种方法是通过全局变量

在单片应用中:

let window.shared.entitlementsAliasMap = <stuff>
let window.shared.autoEnable = <other stuff>
import { Entitlement } from 'Entitlement';
在共享代码的其他地方,比如Foo.ts

import { entitlement} from './entitlement/Entitlement';
假设这甚至可行,它依赖于一些全局变量。关于如何在不使用全局变量的情况下跨包边界共享对象实例,还有其他想法吗?需要消费应用程序向共享代码提供输入,这对于要创建的对象至关重要

如果这是React代码,我可能会在上下文中填充内容,然后断章取义地阅读。但这是在浏览器中运行的普通ES6代码。我正在使用巴别塔,打字脚本和网页包,为了它的价值

更新:

所以,感谢@Antoine和@Bergi的创意。如果问题还不清楚,我道歉。根据他们的反馈,我有一个新想法,我相信它比我以前糟糕的全局变量方法要好。也许可以进一步改进

新的想法是这样的。请原谅打字脚本或JS中的错误;我还没有实现这个修订版。共享代码有几个文件

津贴

export class Entitlement {
   //stuff
   constructor (entitlementsAliasMap: EntitlementsAliasMap, autoEnable: AutoEnableMap) {
     //constructor stuff
   }
   //lots more stuff
}

let instance: Entitlement;

export const getInstance() => {
    if (instance) {
        return instance;
    }
    else throw 'Not initialized';
}

export init(entitlementsAliasMap: EntitlementsAliasMap, autoEnable: AutoEnableMap) {
    if (instance) {
        throw 'Already initialized'; //or just do nothing
    }
    else {
        instance = new Entitlement(entitlementsAliasMap, autoEnable);
    }
}
  export class Entitlement () {
    value1: string = ""
    value2: string = ""
    constructor(value1: string, value2: string) {
      this.value1 = value1
      this.value2 = value2
    }
  }
福茨

import { getInstance } from './entitlement/Entitlement';
//somewhere down below, in code that is not immediately executed
const entitlement = getInstance();
entitlement.<some method name>
在消费型/单色应用程序中,在接近启动时:

import { init, getInstance} from 'Entitlement';

let entitlementsAliasMap = <value>;
let autoEnable = <some other value>;

init(entitlementsAliasMap, autoEnable);

//later, as needed
const entitlement = getInstance();
entitlement.<some method name>

修改后的方法是否更合理?

警告此代码包含错误做法 您不必仅从主项目从包本身初始化实例。请使用单例模式

包名/Singleton.js

class Singleton {
  constructor (value1, value2) {
    if (!Singleton.instance) {
      Singleton.instance = this
      this.value1 = value1
      this.value2 = value2
    }
    return Singleton.instance
  }
}

然后像这样在你的项目中使用它

singletonistance.js

import { Singleton } from 'package-name/Singletone'
const instance = new Singleton(val1, val2)
export default instance
要在另一个包的任何部分使用实例,请使用

import { Singleton } from 'package-name/Singletone'
// Check for initialization before any call
if (Singleton.instance) {
  console.log(Singleton.value1); // should output 'value1';
}
IMHO在理解了您现在需要什么之后,集成依赖注入框架或自己实现它会容易得多,如果您对这些评论感兴趣,请告诉我

我也不鼓励您将此代码用作状态管理。

警告此代码包含错误做法 您不必仅从主项目从包本身初始化实例。请使用单例模式

包名/Singleton.js

class Singleton {
  constructor (value1, value2) {
    if (!Singleton.instance) {
      Singleton.instance = this
      this.value1 = value1
      this.value2 = value2
    }
    return Singleton.instance
  }
}

然后像这样在你的项目中使用它

singletonistance.js

import { Singleton } from 'package-name/Singletone'
const instance = new Singleton(val1, val2)
export default instance
要在另一个包的任何部分使用实例,请使用

import { Singleton } from 'package-name/Singletone'
// Check for initialization before any call
if (Singleton.instance) {
  console.log(Singleton.value1); // should output 'value1';
}
IMHO在理解了您现在需要什么之后,集成依赖注入框架或自己实现它会容易得多,如果您对这些评论感兴趣,请告诉我

我也不鼓励您将此用作状态管理。

不,不要这样做

export let entitlement = new Entitlement(window.shared.entitlementsAliasMap , window.shared.autoEnable);
在库代码内部。让库导出授权构造函数,让应用程序在测试中实例化一次或多次,并共享实例

单片应用程序的代码应该具有

// entitlement.js
import { Entitlement } from 'Entitlement'; // the library module
const entitlementsAliasMap = <stuff>;
const autoEnable = <other stuff>;
export const entitlement = new Entitlement(EntitlementsAliasMap, autoEnable);
不,不要排队

export let entitlement = new Entitlement(window.shared.entitlementsAliasMap , window.shared.autoEnable);
在库代码内部。让库导出授权构造函数,让应用程序在测试中实例化一次或多次,并共享实例

单片应用程序的代码应该具有

// entitlement.js
import { Entitlement } from 'Entitlement'; // the library module
const entitlementsAliasMap = <stuff>;
const autoEnable = <other stuff>;
export const entitlement = new Entitlement(EntitlementsAliasMap, autoEnable);

您还可以借用注入式的思想,使用这样一个非常简单的实现

共享包/权利.ts

export class Entitlement {
   //stuff
   constructor (entitlementsAliasMap: EntitlementsAliasMap, autoEnable: AutoEnableMap) {
     //constructor stuff
   }
   //lots more stuff
}

let instance: Entitlement;

export const getInstance() => {
    if (instance) {
        return instance;
    }
    else throw 'Not initialized';
}

export init(entitlementsAliasMap: EntitlementsAliasMap, autoEnable: AutoEnableMap) {
    if (instance) {
        throw 'Already initialized'; //or just do nothing
    }
    else {
        instance = new Entitlement(entitlementsAliasMap, autoEnable);
    }
}
  export class Entitlement () {
    value1: string = ""
    value2: string = ""
    constructor(value1: string, value2: string) {
      this.value1 = value1
      this.value2 = value2
    }
  }
包装1/foo.ts

import { Entitlement } from 'shared-package/entitlement'
export class Foo {
  constructor (entitlementInstance: Entitlement) {
    console.log(entitlementInstance.value1)
  }
}
包装2/bar.ts

import { Entitlement } from 'shared-package/entitlement'
export class Bar {
  constructor (entitlementInstance: Entitlement) {
    console.log(entitlementInstance.value1)
  }
} 
最后在你的申请中

import { Entitlement } from 'shared-package/entitlement'
import { Foo } from 'package-name1/foo'
import { Bar } from 'package-name2/bar'

const entitlement = new Entitlement('value1', 'value2')
const foo = new Foo(entitlement)
const bar = new Bar(entitlement)


您还可以借用注入式的思想,使用这样一个非常简单的实现

共享包/权利.ts

export class Entitlement {
   //stuff
   constructor (entitlementsAliasMap: EntitlementsAliasMap, autoEnable: AutoEnableMap) {
     //constructor stuff
   }
   //lots more stuff
}

let instance: Entitlement;

export const getInstance() => {
    if (instance) {
        return instance;
    }
    else throw 'Not initialized';
}

export init(entitlementsAliasMap: EntitlementsAliasMap, autoEnable: AutoEnableMap) {
    if (instance) {
        throw 'Already initialized'; //or just do nothing
    }
    else {
        instance = new Entitlement(entitlementsAliasMap, autoEnable);
    }
}
  export class Entitlement () {
    value1: string = ""
    value2: string = ""
    constructor(value1: string, value2: string) {
      this.value1 = value1
      this.value2 = value2
    }
  }
包装1/foo.ts

import { Entitlement } from 'shared-package/entitlement'
export class Foo {
  constructor (entitlementInstance: Entitlement) {
    console.log(entitlementInstance.value1)
  }
}
包装2/bar.ts

import { Entitlement } from 'shared-package/entitlement'
export class Bar {
  constructor (entitlementInstance: Entitlement) {
    console.log(entitlementInstance.value1)
  }
} 
最后在你的申请中

import { Entitlement } from 'shared-package/entitlement'
import { Foo } from 'package-name1/foo'
import { Bar } from 'package-name2/bar'

const entitlement = new Entitlement('value1', 'value2')
const foo = new Foo(entitlement)
const bar = new Bar(entitlement)


我意识到您只需要一些ES6代码,而不是您提到的工具,但我认为为全局状态设置一个可变对象不是一个好主意。您可以使用以下工具之一来实现无全局变量的共享状态,工具多得多,这取决于您的需要。-ReactN-Redux-React内置上下文API。推荐用于包装。您也可以使用共享静态实例的自定义ReactHook,但这应该是您最后的选择。谢谢Antoine,是的,如果这是React代码,事情会更容易,但事实并非如此

在这种情况下。我真的不想为这个用例介绍Redux之类的东西。不过我同意你的观点-我觉得使用全局变量有点恶心,但我没有想到任何更好的方法,它仍然是轻量级和通用的,而不是拖拉整个框架。我意识到你只需要一些ES6代码,而不是你提到的工具,但是,对于全局状态来说,拥有一个可变对象并不是一个好主意。您可以使用以下工具之一来实现无全局变量的共享状态,工具多得多,这取决于您的需要。-ReactN-Redux-React内置上下文API。推荐用于包装。您也可以使用共享静态实例的自定义reactHooks,但这应该是您的最后手段。感谢Antoine,是的,如果这是React代码,事情会更容易,但不是在这种情况下。我真的不想为这个用例介绍Redux之类的东西。不过,我同意你的观点——我觉得使用全局变量有点恶心,但我没有想到任何更好的方法,在不拖拉整个框架的情况下仍然是轻量级和通用的。我想到了单例模式,但我没有看到它与参数一起使用。我不确定工厂模式在这里会如何使用。基于我上面给出的示例,你能不能用一些示例伪代码详细说明一下?为了方便起见,我添加了一个使用单例而不使用工厂的示例。感谢您提供的示例!我现在明白你的建议了。棘手的部分是,我不仅需要单片/消费应用程序中的单例实例,还需要共享代码中的实例,在本例中的不同位置是Foo.ts。ts位于库中,而不是单片应用程序中。您可以将实例传递给任何包。我将添加一个更新。我对您试图实现的目标有点困惑,您总是可以将一个实例传递给不同的依赖项,而这些依赖项不是静态的。我考虑的是单例模式,但我没有看到它与参数一起使用。我不确定工厂模式在这里会如何使用。基于我上面给出的示例,你能不能用一些示例伪代码详细说明一下?为了方便起见,我添加了一个使用单例而不使用工厂的示例。感谢您提供的示例!我现在明白你的建议了。棘手的部分是,我不仅需要单片/消费应用程序中的单例实例,还需要共享代码中的实例,在本例中的不同位置是Foo.ts。ts位于库中,而不是单片应用程序中。您可以将实例传递给任何包。我将添加一个更新。我对您试图实现的目标有点困惑,您总是可以将一个实例传递给不同的依赖项,而不需要它们是静态的。感谢您的反馈,Bergi!棘手的部分是,我不仅需要在单片/消费应用程序中使用授权实例,还需要在共享代码中的实例,在本例中的不同位置使用Foo.ts。ts在库中,而不是在单片应用程序中。共享代码无法实例化类本身,因为它没有所有必需的信息;这仅在消费类/monolothic类中可用。@如果Foo是定义权限构造函数的库的一部分,然后,需要授权的foo应该是它的一部分,以便可以通过它访问它们并保留一个引用,或者应该由单片应用程序通过传递对授权的引用来构造它们。我想我明白你的意思了。根据你和安托万提出的想法,我现在也有了解决这个问题的办法。我认为评论中没有足够的空间来描述它。不确定这里的最佳方法是什么-添加我自己的答案,或者用新的建议答案更新问题。建议?在我最后的评论中,我想我会更新这个问题,从你和Antoine的反馈中提出一个新的想法。对不起,我知道这个问题不是很清楚;我试过了,但我认为我在这方面做得不好,regardI补充道,作为对问题的修正;我不想因为你的想法而受到赞扬:我会投票支持你的两个回答,谢谢你的反馈,伯吉!棘手的部分是,我不仅需要在单片/消费应用程序中使用授权实例,还需要在共享代码中的实例,在本例中的不同位置使用Foo.ts。ts在库中,而不是在单片应用程序中。共享代码无法实例化类本身,因为它没有所有必需的信息;这仅在消费类/monolothic类中可用。@如果Foo是定义权限构造函数的库的一部分,然后,需要授权的foo应该是它的一部分,以便可以通过它访问它们并保留一个引用,或者应该由单片应用程序通过传递对授权的引用来构造它们。我想我明白你的意思了。我也
根据你和安托万提出的想法,现在就想办法解决这个问题。我认为评论中没有足够的空间来描述它。不确定这里的最佳方法是什么-添加我自己的答案,或者用新的建议答案更新问题。建议?在我最后的评论中,我想我会更新这个问题,从你和Antoine的反馈中提出一个新的想法。对不起,我知道这个问题不是很清楚;我试过了,但我认为我在这方面做得不好,regardI补充道,作为对问题的修正;我不想因为你的想法而受到赞扬:我会投票支持你的两个答案。我不确定我是否明白这一点。这可能是我的无知,但也可能是我仍然无法清楚地描述我的用例。请看我修改后的问题,在这里,我添加了一个受您的评论启发的替代实现,尽管不好的部分都是我的。在我的用例中,我有两个包——一个大的单片应用程序和共享库。共享库包含授权类的定义以及使用授权类实例的第二个文件模块。假设是:1。这与第2章中使用的实例相同。实例的任何共享库使用都将在使用应用程序3创建实例之后发生。共享库无法实例化授权类本身,因为它没有所有必要的参数。您的解决方案可以在没有任何不好的部分的情况下工作。实际上,此解决方案只是一种非常通用的方法,可以在没有任何静态实例的情况下实现相同的功能。感谢Antoine提供的所有想法、反馈和您的时间。非常感谢!我不太明白。这可能是我的无知,但也可能是我仍然无法清楚地描述我的用例。请看我修改后的问题,在这里,我添加了一个受您的评论启发的替代实现,尽管不好的部分都是我的。在我的用例中,我有两个包——一个大的单片应用程序和共享库。共享库包含授权类的定义以及使用授权类实例的第二个文件模块。假设是:1。这与第2章中使用的实例相同。实例的任何共享库使用都将在使用应用程序3创建实例之后发生。共享库无法实例化授权类本身,因为它没有所有必要的参数。您的解决方案可以在没有任何不好的部分的情况下工作。实际上,此解决方案只是一种非常通用的方法,可以在没有任何静态实例的情况下实现相同的功能。感谢Antoine提供的所有想法、反馈和您的时间。非常感谢!