最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - GraphQL: Accessing another resolverfield output from a sibling resolver - Stack Overflow

programmeradmin1浏览0评论

need some help. Let say Im requesting the following data:

{
  parent {
    obj1    {
        value1
    }
    obj2    {
        value2
    }
  }
}

And I need the result of value2 in value1 resolver for calculation.

Thought of returning a promise in in value2 and somehow take it in value1 resolver, but what if value2 resolver didn’t run yet?

There`s any way it could be done?

need some help. Let say Im requesting the following data:

{
  parent {
    obj1    {
        value1
    }
    obj2    {
        value2
    }
  }
}

And I need the result of value2 in value1 resolver for calculation.

Thought of returning a promise in in value2 and somehow take it in value1 resolver, but what if value2 resolver didn’t run yet?

There`s any way it could be done?

Share Improve this question asked Jan 11, 2017 at 17:30 alonp99alonp99 1631 gold badge1 silver badge9 bronze badges 3
  • what do you need it for? It maybe an issue with the design of your API. – Aᴍɪʀ Commented Jan 12, 2017 at 3:00
  • I have a large schema that fetches data from a neo4j database. for each entity (let say User, Item/Product) I made a cypher query block. in each entity there are some calculated fields based on the data. for example I have ‘User’ entity, he’s resolver gets raw data from db and calculate ‘rank’ by he’s address, age and other parameters. Now I have the item/product entity that also has a calculated field - ‘price’, that uses the user rank to calculate the final price. – alonp99 Commented Jan 15, 2017 at 17:42
  • Well, if something belongs to a User, from DB or computed, it should be a property on User, not it's sibling. You can always get the resolved value of the parent in inner resolves. – Aᴍɪʀ Commented Jan 15, 2017 at 19:59
Add a comment  | 

3 Answers 3

Reset to default 7

My immediate thought is that you could use the context to achieve something like this. I'd imagine you could have a cache like object mixed with an event emitter to solve the race condition issue.

For example, assume we had some class

class CacheEmitter extends EventEmitter {

  constructor() {
    super();
    this.cache = {};
  }

  get(key) {
    return new Promise((resolve, reject) => {
      // If value2 resolver already ran.
      if (this.cache[key]) {
        return resolve(this.cache[key]);
      }
      // If value2 resolver has not already run.
      this.on(key, (val) => {
        resolve(val);
      });
    })
  }

  put(key, value) {
    this.cache[key] = value;
    this.emit(key, value);
  }
}

Then from your resolvers you could do something like this.

value1Resolver: (parent, args, context, info) => {
  return context.cacheEmitter.get('value2').then(val2 => {
    doSomethingWithValue2();
  });
}

value2Resolver: (parent, args, context, info) => {
  return doSomethingToFetch().then(val => {
    context.cacheEmitter.put('value2', val);
    return val;
  }
}

I haven't tried it but that seems like it may work to me! If you give it a shot, I'm curious so let me know if it works. Just for book keeping you would need to make sure you instantiate the 'CacheEmitter' class and feed it into the GraphQL context at the top level.

Hope this helps :)

According to graphql-resolvers: "GraphQL currently does not support a field to depend on the resolved result of another field". Using an EventEmiter seems like a very off-spec way of achieving this. graphql-tools offers helper functions that allow you to compose resolvers in a number of ways that should help you.

You can load value2 of obj2 in your obj1 resolver again, if you are caching things that should not pose any performance issues.

发布评论

评论列表(0)

  1. 暂无评论