【发布时间】:2019-11-01 15:45:51
【问题描述】:
我正在使用 node 和 express 为应用程序构建后端。
我在不同的文件中分隔了不同的代码部分:例如,与访问数据库有关的所有内容都在文件 DBService.js 中,如果我想执行与我的用户相关的任何操作,我有一个 UserService.js 文件可以完成所有操作应用需要用户,并使用 DBService.js 将用户保存在数据库中。
我知道我的代码中确实存在一些循环依赖项,但到目前为止一切正常。我在几乎所有事情上都使用 GraphQL,但我添加了一个普通端点来获取一个给定 ID 的文件。
我确实需要 index.js(节点应用程序的入口点)中的 FileService.js 来提供文件,这部分效果很好。问题是在我还需要 FileService.js 的另一个文件 (ZoneService.js) 中,它返回一个空对象。
我知道这是问题所在,因为如果我删除 index.js 文件中的 require,问题就会消失。
这些是导致循环依赖的路径。 '->' 表示上一个服务需要下一个。
FileService -> ZoneService -> FileService
FileService -> ZoneService -> FileUploadService -> FileService
这可能看起来很傻,但我需要这个,因为我认为将每个实体的 graphQL 类型定义和解析器保留在它自己的文件中是一个很好的举措。
我将尝试解释我对第一条路径的推理:
- 我想抓取来自某个区域的文件,所以这个函数进入 FileService。然后我使用 ZoneService 获取给定区域 ID 的文件 ID,然后我从数据库中获取路径
- ZoneService 需要 FileService 来解析区域实体中的“文件”字段
我可以将这个函数移动到 ZoneService 并从那里获取文件,但这会有点破坏我分离关注点的所有逻辑。
我想知道的是解决此问题的最佳方法,以使其不再发生,以及如何避免。
我会发布一些代码,但我不确定如果您认为有必要,请告诉我。
提前致谢!
编辑 - 这是一些代码:
文件服务.js
//Import services to use in resolvers
const EditService = require("./EditService.js")
const ZoneService = require("./ZoneService.js")
//Resolvers
const resolvers = {
Query: {
getFileById: (parent, {_id}) => {
return getFileById(_id)
},
getFilesById: (parent, {ids}) => {
return getFilesById(ids)
},
getFilesByZoneId: (parent, {_id}) => {
return getFilesByZoneId(_id)
},
},
File: {
editHistory: file => {
return EditService.getEditsById(file.editHistory)
},
fileName: file => {
return file.path.split('\\').pop().split('/').pop();
},
zone: file => {
return ZoneService.getZoneById(file.zone)
}
}
}
ZoneService.js
//Import services to use in resolvers
const UserService = require("./UserService.js")
const FileService = require("./FileService.js")
const EditService = require("./EditService.js")
const ErrorService = require("./ErrorService.js")
const FileUploadService = require("./FileUploadService.js")
//Resolvers
const resolvers = {
Query: {
getZone: (parent, {_id, label}) => {
return _id ? getZoneById(_id) : getZoneByLabel(label)
},
getZones: () => {
return getZones()
},
},
Zone: {
author: zone => {
return UserService.getUserById(zone.author)
},
files: zone => {
if(zone.files && zone.files.length > 0) return FileService.getFilesById(zone.files)
else return []
},
editHistory: zone => {
return EditService.getEditsById(zone.editHistory)
}
},
Mutation: {
createZone: async (parent, input, { loggedUser }) => {
return insertZone(input, loggedUser)
},
editZone: async (parent, input, { loggedUser }) => {
return editZone(input, loggedUser)
},
removeZone: async (parent, input, { loggedUser }) => {
return removeZone(input, loggedUser)
}
},
}
【问题讨论】:
-
如果没有至少一些(截断的)示例代码或指向存储库的链接,就很难理解您对依赖项的描述,或者它们如何适合您的架构。
-
FileService 是一个对象/类吗?
-
@DanielRearden 我为 FileService 和 ZoneService 添加了代码示例,如果您需要更多,请告诉我。
-
@RandyCasburn FileService 是一个模块(所以它就像一个对象,对吧?),它包含函数和带有解析器和类型定义等内容的 graphQL 对象。当我需要文件时,我正在使用 module.exports 使它们可用。
标签: javascript commonjs apollo-server