GraphQL: доступ к другому распознавателю/выходу поля из родственного распознавателя

нужна помощь. Допустим, я запрашиваю следующие данные:

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

И мне нужен результат value2 в распознавателе value1 для расчета.

Думал вернуть промис в value2 и каким-то образом принять его в распознавателе value1, но что, если распознаватель value2 еще не запущен?

Есть ли способ это сделать?


person alonp99    schedule 11.01.2017    source источник
comment
для чего тебе это? Это может быть проблема с дизайном вашего API.   -  person Aᴍɪʀ    schedule 12.01.2017
comment
У меня есть большая схема, которая извлекает данные из базы данных neo4j. для каждого объекта (скажем, Пользователь, Товар/Продукт) я создал блок запроса шифрования. в каждой сущности есть несколько вычисляемых полей на основе данных. например, у меня есть объект «Пользователь», его преобразователь получает необработанные данные из БД и вычисляет «ранг» по его адресу, возрасту и другим параметрам. Теперь у меня есть сущность товара/продукта, которая также имеет вычисляемое поле — «цена», которое использует рейтинг пользователя для расчета окончательной цены.   -  person alonp99    schedule 15.01.2017
comment
Что ж, если что-то принадлежит User, из БД или вычислено, оно должно быть свойством User, а не родственным. Вы всегда можете получить разрешенное значение родителя во внутренних разрешениях.   -  person Aᴍɪʀ    schedule 15.01.2017


Ответы (3)


Моя немедленная мысль заключается в том, что вы могли бы использовать контекст для достижения чего-то подобного. Я полагаю, что вы могли бы иметь кеш-подобный объект, смешанный с эмиттером событий, чтобы решить проблему состояния гонки.

Например, предположим, что у нас есть некоторый класс

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);
  }
}

Затем из ваших преобразователей вы можете сделать что-то вроде этого.

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;
  }
}

Я не пробовал, но мне кажется, что это может сработать! Если вы дадите ему шанс, мне любопытно, так что дайте мне знать, если это работает. Просто для ведения бухгалтерского учета вам нужно будет убедиться, что вы создаете экземпляр класса CacheEmitter и передаете его в контекст GraphQL на верхнем уровне.

Надеюсь это поможет :)

person mparis    schedule 12.01.2017
comment
Спасибо, мне нравится идея... Если я пойду по этому пути, мне все равно нужно будет решить случай, когда запрос не будет иметь значение2, я могу вызвать преобразователь, но мне нужно как-то вызвать все родительские преобразователи. Также заставил меня задуматься о том, что люди делают, чтобы убедиться, что какой-то резолвер не зависает в ответе от graphql. Спасибо еще раз попробую - person alonp99; 15.01.2017
comment
А как установить cacheEmitter на context? Например. в express-graphql context уже установлен на объект запроса. - person Alex; 12.04.2018
comment
@mpais, как я могу установить cacehEmitter? это за узел? - person muescha; 06.05.2020

Согласно graphql-resolvers: «GraphQL в настоящее время не поддерживает зависимость поля от разрешенного результата другого поля». Использование EventEmiter кажется очень нестандартным способом достижения этого. graphql-tools предлагает вспомогательные функции, которые позволяют создавать преобразователи несколькими способами, которые должны вам помочь.

person leanne1    schedule 11.12.2018
comment
Не могли бы вы предложить какой-либо пример для достижения того же, используя graphql-tools - person User3250; 10.05.2021

Вы можете снова загрузить value2 из obj2 в свой преобразователь obj1, если вы кешируете вещи, которые не должны создавать проблем с производительностью.

person Behlül    schedule 04.03.2021