节点依赖项容器无法按预期工作

时间:2019-06-04 11:24:23

标签: javascript node.js dependency-injection node-modules

我有一个这样的DI容器:

# di-container.js
const container = {
    fileReader: require("./file-reader"),
    csvReader: require("./csv-reader"),
}

module.exports = {
    container
}

csv-reader.js看起来像这样:

# csv-reader.js
const { container } = require("./di-container")

async function readFileAsCSV(path)
    const fileContents = await container.fileReader.readFileContents(path)
    return fileContents.split("\n")
                       .map(line => line.split(","))
}

我有一个测试文件csv-reader.spec.js

# csv-reader.spec.js
const { container } = require("./di-container")

describe("csvReader", () => {
    it("should read cells from file", async () => {
        const fakeCSV = "\"Name\",\"Age\"\n\"Bob Smith\",\"32\""
        container.fileReader.readFileContents = (_) => fakeCSV

        const result = container.csvReader.readFileAsCSV()

        # Do some assertions...
    })
})

运行测试时,它会失败并显示错误(堆栈跟踪行号不同,示例有所不同):

TypeError: Cannot read property 'fileReader' of undefined
 at Object.readFileAsCSV (csv-reader.js:8:42)
 at Context.it (csv-reader.spec.js:15:44)
 at processImmediate (internal/timers.js:443:21)

我希望containercsv-reader.spec.js中对csv-reader.js的内存引用是相同的,所以我应该能够更改container.fileReader.readFileContents并且csv-reader将使用模拟功能。

如果我从csvReader: require("./csv-reader")中删除了di-container.js行,并在const csvReader = require("./csv-reader")中使用了csv-reader.spec.js,则测试通过。这将暗示在container中创建依赖项的顺序有些奇怪。

我尝试在fileReader中重新排列csvReadercontainer的顺序,并将它们更改为类似于container.fileReader = ...而不是内联实例化,但这没有用。

1 个答案:

答案 0 :(得分:0)

您有一个依赖项module cycle

您的di-container.js文件需要csv-reader.js,而csv-reader.js文件需要di-container.js,这形成一个循环。

因此,require("./di-container")null文件中返回csv-reader.js。 因为require("./di-container")null,所以解构的container将是未定义的。 这样,您就得到了您提到的错误。

您需要重新设计功能,并可能要考虑将它们放置在何处。


从广义上讲,只需将两个文件中要使用的功能分开,然后将它们放入common.js

然后,在common.jscsv-reader.js内输入di-container.js


  

如果我从以下位置删除csvReader:require(“ ./ csv-reader”)行   di-container.js并在其中使用const csvReader = require(“ ./ csv-reader”)   csv-reader.spec.js,然后测试通过。这将建议一些   与容器中依赖项的排列顺序不一致   已创建。

如果您不需要csv-reader.js中的di-container.js,那么周期就中断了,因此一切正常。