我最近发现,因为我的一些屏蔽规则中进行了异步调用,所以导致我的数据加载器批处理函数被多次调用,而它们只应该被调用一次,这给我带来了 N+1 问题。
我相信这是由于
dataloader
库要求所有批处理函数调用都发生在同一个事件循环“tick”(source)期间,而我的屏蔽规则中进行的异步调用阻止了这种情况。
这是我在我的
app中传递给
useFactory
的 GraphQLModule
函数:
useFactory(dataloaderService: DataloaderService, usersService: UsersService) {
return {
context: async ({ req }: { req: Request }) => {
const loaders = dataloaderService.getLoaders();
const services = { usersService };
return { loaders, services };
},
transformSchema: (schema: GraphQLSchema) => {
schema = applyMiddleware(schema, shieldPermissions);
return schema;
},
};
},
有没有办法同时使用数据加载器和像 GraphQL Shield 这样的授权库?我当前的配置是否有任何问题可能导致此问题?
传递
batchScheduleFn
的选项解决了问题:
private _createGroupsLoader() {
return this._getDataLoader<number, Group>(
async (groupIds) =>
this.groupsService.getGroupsBatch(groupIds as number[]),
{
batchScheduleFn: (callback) => setTimeout(callback, 5),
}
);
}
在不传递
batchScheduleFn
的情况下,数据加载器在内部使用它自己的调度程序,该调度程序使用 process.nextTick
或 setImmediate
。
使用 5 ms 的原因:
我们当前的启发是将执行交回主线程 每 5 毫秒。 5ms 并不是一个神奇的数字,重要的是它 即使在 120fps 设备上也比单帧小,因此不会阻塞 动画。
来源:https://dev.to/tsirlucas/integrating-dataloader-with-concurrent-react-53h1