При использовании промежуточного программного обеспечения в Express сбой вызова стороннего API - PullRequest
0 голосов
/ 24 декабря 2018

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

router.use('/update-database', (req, res) => {
  dbUpdate()
  .then(() => res.json({
    success: true,
    error: null,
  }));
});

Моя dbUpdate функция включает в себя довольно много вызовов API для третьего-партии, и она всегда потерпит неудачу с той, которая займет больше всего времени.Я помещаю логи в свою функцию dbUpdate и в консоли браузера вижу что-то вроде ниже:

first step completed
second step completed
third, fourth and fifth steps started concurrently
third step completed
fifth step completed
Error: Request failed with status code 408(sometimes 504 too)
GET /api/update-database - - ms - -

в консоли браузера, я вижу

GET http://localhost:3000/api/update-database net::ERR_EMPTY_RESPONSE
Uncaught (in promise) TypeError: Failed to fetch

Если я выполню dbUpdate Функция вручную на моем сервере, он пройдет без каких-либо проблем.Я пытался увеличить мой запрос и время ответа, но не повезло.Может кто-то пролить свет на это?

Вот точка входа в мою настройку бэкэнда:

import express from 'express';
import logger from 'morgan';
import mongoose from 'mongoose';
import getItemsFromType from './optimizely';
import Project from './models/project';
import Campaign from './models/campaign';
import Experiment from './models/experiment';
import KnownPage from './models/knownPage';
import Page from './models/page';

require('dotenv').config();

const app = express();
const router = express.Router();
const API_PORT = process.env.API_PORT || 3001;

const projectIds = [];

app.use(logger('dev'));
app.use('/api', router);

mongoose.connect(process.env.DB_URI, { useNewUrlParser: true });
mongoose.Promise = global.Promise;
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'MongoDB connection error: '));

const init = () => {
  console.log('Clearing all models');
  return Promise.all([
    Project.deleteMany({}), Campaign.deleteMany({}), Experiment.deleteMany({}), KnownPage.deleteMany({}), Page.deleteMany({})]);
};

// update collections
const updateProjectCollection = () => getItemsFromType('project')
  .then(data => Project.insertMany(data.map((e) => {
    projectIds.push(e.id);
    return {
      id: e.id,
      name: e.name,
      status: e.status,
      created: e.created,
      last_modified: e.last_modified,
    };
  })))
  .then(() => {
    console.log('project collection update completed');
    return projectIds;
  })
  .catch(err => console.log(err));

const updateCampaignCollection = () => Promise.all(projectIds.map(prjId => getItemsFromType('campaign', prjId)
  .then(data => Campaign.insertMany(data.map(e => ({
    id: e.id,
    project_id: e.project_id,
    name: e.name,
    page_ids: e.page_ids,
    status: e.status,
    created: e.created,
    last_modified: e.last_modified,
  }))))
  .then((docs) => {
    for (let i = 0; i < docs.length; i++) {
      if (docs[i].page_ids) {
        return Promise.all((docs[i].page_ids).map(pageId => new KnownPage({ id: pageId }).save()));
      }
      return new KnownPage({ id: -1 }).save();
    }
  })
  .catch(err => console.log(err))))
  .then(() => { console.log('campaign collection update completed'); });

const updateExperimentCollection = () => Promise.all(projectIds.map(prjId => getItemsFromType('experiment', prjId)
  .then(data => Experiment.insertMany(data.map(e => ({
    id: e.id,
    project_id: e.project_id,
    name: e.name,
    page_ids: e.page_ids,
    status: e.status,
    created: e.created,
    last_modified: e.last_modified,
  }))))
  .then((docs) => {
    for (let i = 0; i < docs.length; i++) {
      if (docs[i].page_ids) {
        return Promise.all((docs[i].page_ids).map(pageId => new KnownPage({ id: pageId }).save()));
      }
      return new KnownPage({ id: -1 }).save();
    }
  })
  .catch(err => console.log(err))))
  .then(() => { console.log('experiment collection update completed'); });

const updatePageCollection = () => Promise.all(projectIds.map(prjId => getItemsFromType('page', prjId)
  .then(data => Page.insertMany(data.map(e => ({
    id: e.id,
    project_id: e.project_id,
    name: e.name,
    archived: e.archived,
    created: e.created,
    last_modified: e.last_modified,
  }))))))
  .then(() => { console.log('page collection update completed'); })
  .catch(err => console.log(err));

const dbUpdate = () => init()
  .then(() => updateProjectCollection())
  .then(() => {
    console.log('project ids are available to use');
    return Promise.all([
      updateCampaignCollection(),
      updateExperimentCollection(),
      updatePageCollection(),
    ]);
  });

router.get('/', (req, res) => {
  res.json({ message: 'Welcome!' });
});

router.use('/update-database', (req, res) => {
  dbUpdate()
    .then(() => res.json({
      success: true,
      error: null,
    }));
});

app.listen(API_PORT, () => console.log(`Listening on port ${API_PORT}`));

и вот как определяется getItemsFromType в optimizely.js:

import axios from 'axios';

require('dotenv').config();

const perPage = 100;

const getItemsFromType = (type, prjId = 0, pagination = 1, arr = []) => {
  const url = (type === 'project') ? `https://api.optimizely.com/v2/projects?per_page=${perPage}&page=${pagination}` : `https://api.optimizely.com/v2/${type}s?project_id=${prjId}&per_page=${perPage}&page=${pagination}`;

  return axios.get(url, {
    headers: {
      Authorization: `Bearer 2:${process.env.OPTLY_API_KEY}`,
    },
  })
    .then((data) => {
      arr = arr.concat(data.data);
      if (data.data.length < 100) { return arr; }
      return getItemsFromType(type, prjId, ++pagination, arr);
    })
    .catch((err) => {
      console.log(`in getAllProjects: ${err}`);
    });
};

export default getItemsFromType;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...