Я использую маршрут, который я установил в своем бэкэнде, чтобы обновить свою базу данных, которая может быть инициирована из моего клиента:
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;