如何在Typescript中将自定义对象参数传递给Dataloader?

gupuwyp2  于 2023-06-24  发布在  TypeScript
关注(0)|答案(1)|浏览(168)

我正在尝试将一个对象作为键传递给Dataloader的示例。我知道我必须做一个自定义的缓存键函数,但我不知 prop 体怎么做。我在网上学习这个教程:https://www.youtube.com/watch?v=I6ypD7qv3Z8&t=41601s&ab_channel=BenAwad
它有点过时了,所以我不能完全理解它。
我这样调用dataload函数:

  1. @FieldResolver(()=> Int, {nullable:true})
  2. async voteStatus(
  3. @Root() post: Post,
  4. @Ctx() {upvoteLoader, req}: MyContext){
  5. if (!req.session.userId) {
  6. return null
  7. }
  8. const key = {
  9. postId: post.id,
  10. userId: req.session.userId
  11. }
  12. const upvote = await upvoteLoader.load(key)
  13. console.log("upvote data: ", upvote)
  14. return null
  15. // const upvote = await upvoteLoader.loadMany(key)
  16. // console.log("after")
  17. // return upvote ? upvote.value : null
  18. }

查看DataLoader的代码,我得到了这样的结果:

  1. declare class DataLoader<K, V, C = K> {
  2. constructor(
  3. batchLoadFn: DataLoader.BatchLoadFn<K, V>,
  4. options?: DataLoader.Options<K, V, C>,
  5. ); ... }
  6. declare namespace DataLoader {
  7. // If a custom cache is provided, it must be of this type (a subset of ES6 Map).
  8. export type CacheMap<K, V> = {
  9. get(key: K): V | void;
  10. set(key: K, value: V): any;
  11. delete(key: K): any;
  12. clear(): any;
  13. };
  14. ...
  15. /**
  16. * Default `key => key`. Produces cache key for a given load key. Useful
  17. * when keys are objects and two objects should be considered equivalent.
  18. */
  19. cacheKeyFn?: (key: K) => C;

我为该高速缓存键创建了一个自定义函数。我试过几种不同的方法。(我以后会给你起更好的名字)
方式一:

  1. class C {
  2. postId: number;
  3. userId: number;
  4. constructor(postId:number, userId: number) {
  5. this.postId = postId
  6. this.userId = userId
  7. }
  8. }
  9. function cacheKeyFn({postId, userId}: {postId:number, userId: number }) {
  10. const c = new C(postId, userId)
  11. return c;
  12. }
  13. export const createUpvoteLoader = () =>
  14. new DataLoader<{postId: number; userId: number}, Upvote | null, C> (async (keys)=>{
  15. console.log("my keys are ", keys)
  16. const upvotes = await Upvote.findBy({
  17. postId: In((keys).postId as any[]),
  18. userId: In(keys as any[])
  19. })
  20. const UpvoteIdsToUpvote: Record<string, Upvote> = {}
  21. upvotes.forEach(upvote => {
  22. UpvoteIdsToUpvote[`${upvote.userId}|${upvote.postId}`] = upvote
  23. })
  24. return keys.map(key => UpvoteIdsToUpvote[`${key.userId}|${key.postId}`])
  25. }, {cacheKeyFn})

方式二:

  1. function cacheKeyFn({postId, userId}: {postId:number, userId: number }) {
  2. return {"postId": postId, "userId":userId};
  3. }
  4. export const createUpvoteLoader = () =>
  5. new DataLoader<{postId: number; userId: number}, Upvote | null> (async (keys)=>{
  6. const upvotes = await Upvote.findBy({
  7. postId: In(keys as any[]),
  8. userId: In(keys as any[])
  9. })
  10. const UpvoteIdsToUpvote: Record<string, Upvote> = {}
  11. upvotes.forEach(upvote => {
  12. UpvoteIdsToUpvote[`${upvote.userId}|${upvote.postId}`] = upvote
  13. })
  14. return keys.map(key => UpvoteIdsToUpvote[`${key.userId}|${key.postId}`])
  15. }, {cacheKeyFn})

方式3(理智):

  1. export const createUpvoteLoader = () =>
  2. new DataLoader<{postId: number; userId: number}, Upvote | null> (async (keys)=>{
  3. const upvotes = await Upvote.findBy({
  4. postId: In(keys as any[]),
  5. userId: In(keys as any[])
  6. })
  7. const UpvoteIdsToUpvote: Record<string, Upvote> = {}
  8. upvotes.forEach(upvote => {
  9. UpvoteIdsToUpvote[`${upvote.userId}|${upvote.postId}`] = upvote
  10. })
  11. return keys.map(key => UpvoteIdsToUpvote[`${key.userId}|${key.postId}`])
  12. })

不断出现的错误是:driverError: error: invalid input syntax for type integer: "{"postId":317,"userId":2}"

vcirk6k6

vcirk6k61#

cacheKeyFn的输出应该是像stringnumber这样的简单值。我认为这应该起作用:

  1. new DataLoader<{postId: number; userId: number}, Upvote | null, string> (
  2. async keys => { ... }, // batchLoadFn
  3. {
  4. cacheKeyFn: ({postId: number, userId: number}) => `${postId}:${userId}`
  5. }
  6. );

要测试键的唯一性,DataLoader将调用cacheKeyFn并使用结果进行比较。在这里,我们创建一个字符串${postId}:${userId}。批量加载fn将接收原始对象,而不是字符串。参见:https://stackoverflow.com/a/59349421

相关问题