Отправка данных из Express в React через Contentful API

Я решил попробовать безголовую CMS от Contentful, и у меня возникла проблема с их клиентом API. Я пытаюсь выйти замуж за экспресс с реакцией на рендеринг на стороне сервера, и я использую this repo в качестве отправной точки.

Мой экспресс-роутер

Создайте маршрут, который может вызывать мой компонент React:

createApiRouter(app) {
    const router = express.Router();

    this.createHeroesRoute(router);
    // this.createDetailedBillRoute(router);        
    return router;
},

createHeroesRoute(router) {
    router.get('/get-heroes', (req, res) => {
      this.getHeroes((err, data) => {
        if(!err) {
          res.json(data);                                    
        } else {
          res.status(500).send(err);
        }
      });
    });
},

Получите данные из Contentful

getHeroes(callback) {
    contentfulClient.getEntries({content_type: 'sectionHeroes'})
      .then((entries) => {
        //serilizations is a custom data serializer to format this data, it's working fine
        return JSON.parse(serializations.serializeMainSection(entries.items[0]))
      })
      .catch((error) => error );
}

Компонент My React

Запросить данные

static requestData(params, domain = '') {
    return axios.get(`${domain}/api/get-heroes`);
}

Установите состояние компонента на полученные данные

componentDidMount() {
    this.constructor.requestData().then((response) => {
      this.setState(response.data);
    }).catch((err) => {
      throw new Error(err);
    });
}

Сбой происходит в getHeroes методе внутри экспресса. Поскольку клиент contentful - это обещание, я не знаю, как заставить getHeroesRoute ждать ответа от getHeroes. Как я могу это сделать?


person thatgibbyguy    schedule 11.08.2016    source источник
comment
Я отказался от использования клиента api Contentful и вместо этого использую node-rest-client и сам создаю контентные абстракции. Я все еще хотел бы точно знать, почему ответы, основанные на обещаниях, не работают, но для меня это больше не проблема.   -  person thatgibbyguy    schedule 12.08.2016


Ответы (2)


Вам нужно вызвать обратный вызов, который createHeroesRoute () передает getHeroes (), когда обещание разрешается. Изменение getHeroes () на это должно сделать это:

getHeroes(callback) {
    contentfulClient.getEntries({content_type: 'sectionHeroes'})
        .then((entries) => {
            callback(JSON.parse(serializations.serializeMainSection(entries.items[0])));
        })
       .catch((error) => error );
}

Предполагая, что JSON.parse все работает.

person Ben Sidelinger    schedule 11.08.2016
comment
Спасибо за ответ. Если изменить его на это, теперь просто рендерится пустой объект ... Это очень странно. - person thatgibbyguy; 12.08.2016
comment
Фактически, изменение его на это вызывает синтаксическую ошибку, хотя мой терминал не сообщает мне, где произошла ошибка. - person thatgibbyguy; 12.08.2016
comment
Вам нужно будет отладить это шаг за шагом. Понятия не имею, что такое сериализации. serializeMainSection () не делает, ни то, что содержит entry.items [0]. Я бы рекомендовал инкрементное ведение журнала всего, что вы пытаетесь сделать. Примерно так: contentfulClient.getEntries ({content_type: 'sectionHeroes'}) .then ((entries) = ›{callback (JSON.parse (serializations.serializeMainSection (entries.items [0])));}) .catch ( (error) = ›error); - person Ben Sidelinger; 15.08.2016
comment
Получилось довольно запутанно, очевидно, SO не форматирует код в комментариях, как в ответах. В любом случае, я бы записал в console.log каждый шаг и посмотрел, что происходит. Сделайте console.log(entries); сразу, чтобы убедиться, что вы получаете ожидаемые данные, это должен быть объект с массивом .items, содержащий хотя бы один элемент. Если все выглядит хорошо, убедитесь, что функция serializeMainSection () возвращает строку JSON, иначе JSON.parse задохнется. - person Ben Sidelinger; 15.08.2016
comment
Да, я кое-что упустил, потому что я уже сделал то, что вы предлагаете. Проблема в том, что довольный клиент просто не возвращает данные так, как ожидает сервер. То, что вас смущает, было тем, что я сделал для сериализации данных так, как я думал, что сервер хотел (и это помогло), но затем довольный клиент вернул пустое обещание, которое сервер пытался запустить, в результате чего ничего не работало. - person thatgibbyguy; 16.08.2016
comment
Так вы все еще получаете сообщение об ошибке? Что там написано? Являются ли результаты этого JSON.parse () тем, что вы ожидаете передать обратному вызову? - person Ben Sidelinger; 16.08.2016
comment
Да, он имеет нужную мне форму, но сервер в res.json принимает его как просто объект Promise, а не данные, возвращаемые в .then - person thatgibbyguy; 16.08.2016
comment
Ааа, ваш обратный вызов ищет две вещи: ошибку и данные, поэтому вам нужно сделать callback(false, JSON.parse(..... Также убедитесь, что данные правильно передаются в обратный вызов после if (!err) { в коде вашего сервера. - person Ben Sidelinger; 16.08.2016
comment
На самом деле, что нужно было сделать, это сначала проанализировать данные, чтобы они отображались в виде списка, а не объекта, а затем изменить обратный вызов, чтобы он принимал только данные (без ошибок), потому что contentful возвращает ошибки в той же форме, что и данные. Это все исправило. - person thatgibbyguy; 17.08.2016

Это не проблема с API, вы не ждете разрешения обещания перед отправкой ответа. Ваш код должен выглядеть так:

getHeroes() {
  return contentfulClient.getEntries({content_type: 'sectionHeroes'})
    .then((entries) => {
      //serilizations is a custom data serializer to format this data, it's working fine
      return JSON.parse(serializations.serializeMainSection(entries.items[0]))
    })
}

и в вашем экспресс-роутере:

createApiRouter(app) {
  const router = express.Router();

  this.createHeroesRoute(router);
  // this.createDetailedBillRoute(router);        
  return router;
},

createHeroesRoute(router) {
  router.get('/get-heroes', (req, res) => {
    this.getHeroes().then((data) => {
      res.json(data);
    }).catch((err) => {
       res.status(500).send(err);
    })
  });
}
person Khaled Garbaya    schedule 10.11.2016