我正在使用我在后端设置的路由来更新可以从客户端启动的数据库:
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}`));
这是在optimize.js中定义getItemsFromType
的方式:
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;