我的一个节点控制器遇到了一个奇怪的问题。对于上下文,在针对此特定控制器的POST请求中,我将对象存储在mongo数据库中,并将对象的必要部分写入文件。有一个已经存在的网站,它直接与服务器连接,但我正在为想要自定义界面的客户编写REST api。 (我没有写节点服务器或网站。)
我的问题是,出于某种原因,在这种情况下写入文件的值在“post”之后显示为Null,如下所示: { “腿”:[{ “PTU”:{ “倾斜”:{}, “PAN”:{}}},{ “音频”:{ “静音”:假, “体积”:0}, “PTU” :{ “倾斜”:{ “ABS”:NULL} “锅”:{ “ABS”:空}}},{ “音频”:{ “静音”:真, “体积”:0}, “PTU” :{ “倾斜”:{ “ABS”:NULL} “锅”:{ “ABS”:空}}}]}
但是,网站上的表格填写正确,如果我从网站上按“保存”,文件就会正确更新。即。
{"legs":[{"ptu":{"tilt":{"abs":0},"pan":{"abs":0}}},{"audio":{"track":"/home/rahd/ult0316-p002/resources/tracks/Maid with the Flaxen Hair.mp3","vol":0,"mute":false},"ptu":{"tilt":{"abs":10},"pan":{"abs":10}}},{"audio":{"track":null,"vol":0,"mute":true},"ptu":{"tilt":{"abs":10},"pan":{"abs":10}}}]}
这是我的邮递员请求,它以原始JSON格式发送:
{
"name": "NicksCoolTour3",
"location": "/home/rahd/ult0316-p002/resources/tours/5982374cb492c516c20c40d0.json",
"legs": [
{
"audio": {
"mute": true,
"volPercent": 0,
"vol": -120,
"track": null
},
"ptu": {
"poi": "59823726b492c516c20c40cd",
"tilt": {
"vel": 5,
"rel": 0,
"abs": 0
},
"pan": {
"vel": 5,
"rel": 0,
"abs": 0
},
"direction": "quickest"
},
"time": 0,
"velMode": "time",
"ptuMode": "poi"
},
{
"_id": "5982374cb492c516c20c40d2",
"audio": {
"mute": false,
"volPercent": 100,
"vol": -120,
"track": "5983222d79930a1dbd4d94ac"
},
"ptu": {
"tilt": {
"vel": 5,
"rel": 10,
"abs": 0
},
"pan": {
"vel": 5,
"rel": 10,
"abs": 0
},
"direction": "quickest"
},
"time": 0,
"velMode": "time",
"ptuMode": "rel"
},
{
"_id": "5982374cb492c516c20c40d1",
"audio": {
"mute": true,
"volPercent": 100,
"vol": -120,
"track": "59823711b492c516c20c40cc"
},
"ptu": {
"tilt": {
"vel": 5,
"rel": 0,
"abs": 0
},
"pan": {
"vel": 5,
"rel": 0,
"abs": 0
},
"direction": "quickest"
},
"time": 0,
"velMode": "time",
"ptuMode": "rel"
}
]
}
这是我的POST控制器:
router.post('/',function (req, res, next){
var new_tour = new Tour(req.body);
new_tour._id = new mongoose.Types.ObjectId;
new_tour.save( function(err, tour) {
if (err) return next(err);
res.json({ message: "tours database sucessfully updated" });
});
});
我不确定是什么导致这种情况,似乎数据库正在获取正确的值,但将请求写入文件的函数行为不正常。
这是处理文件写入的模式:
var mongoose = require("mongoose")
, fs = require('fs')
, path = require('path')
, resources = require(path.join(__dirname, '..', '..', 'config', 'resources'));
var schema = new mongoose.Schema({
name: { type: String, default: '', unique: true, required: true },
location: { type: String },
legs: [{
ptuMode: { type: String, default: 'abs' }, // abs || rel || poi
velMode: { type: String, default: 'vel' }, // vel || time
time: { type: Number, default: 0 }, // vel || time
ptu: {
direction: { type: String, default: 'cw' }, // cw || ccw
pan: {
rel: { type: Number },
abs: { type: Number },
vel: { type: Number },
},
tilt: {
rel: { type: Number },
abs: { type: Number },
vel: { type: Number },
},
poi: {
type: mongoose.Schema.Types.ObjectId,
ref: 'POI'
},
},
audio: {
mute: { type: Boolean },
vol: { type: Number },
volPercent: { type: Number },
track: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Track'
},
}
}]
},
{
timestamps: true
});
schema.pre('save', function (next) {
var tour = this;
if (!tour.location || tour.location.length < 1) {
tour.location = path.join(resources.tours, tour._id + '.json');
}
tour.writeToFile(function (err) {
console.error(err);
});
next();
});
schema.post('remove', function (tour) {
if (tour.location && tour.location.length > 0) {
fs.exists(tour.location, function (exists) {
if (exists) {
fs.unlink(tour.location);
console.log('Deleted Tour: ' + tour.location);
} else {
console.log('Tour not found, so not deleting file.');
}
});
}
});
schema.methods.writeToFile = function (callback) {
function saveToFile(tour, callback) {
var filePath = tour.location;
var name = tour.name;
delete tour.location;
delete tour.name;
delete tour.createdAt;
delete tour.updatedAt;
delete tour._id;
delete tour.__v;
for (li in tour.legs) {
var leg = tour.legs[li];
var index = li;
if (typeof index === 'string') {
index = parseInt(li);
}
delete leg._id;
// Delete rel, force abs
delete leg.ptu.tilt.rel;
delete leg.ptu.pan.rel;
if (leg.audio.hasOwnProperty("volPercent")) {
var x = leg.audio.volPercent;
delete leg.audio.volPercent;
var n = -120;
if (x > 0) {
var val = Math.pow((x / 100), 4);
n = Math.max(20 * Math.log10(val), -120)
}
leg.audio.vol = n;
}
if (index == 0) {
delete leg.ptu.pan.vel;
delete leg.ptu.tilt.vel;
} else {
if (leg.ptu.pan.vel == 0) {
leg.ptu.pan.vel = 50;
}
if (leg.ptu.tilt.vel == 0) {
leg.ptu.tilt.vel = 50;
}
if (leg.ptu.direction === 'ccw') {
leg.ptu.pan.vel = -(Math.abs(leg.ptu.pan.vel));
}
}
if (leg.ptu.direction === 'quickest') {
delete leg.ptu.tilt.vel;
delete leg.ptu.pan.vel;
}
if (typeof (leg.audio.track) === 'object' && leg.audio.track !== null) {
leg.audio.track = leg.audio.track.location;
}
// Handle Delay
if (leg.ptuMode == 'delay') {
delete leg.ptu.pan;
delete leg.ptu.tilt;
} else {
delete leg.ptu.delay;
}
delete leg.ptu.poi;
delete leg.time;
delete leg.ptu.direction;
delete leg.ptuMode;
delete leg.velMode;
if (index == 0) {
delete leg.audio;
}
}
if (filePath && filePath.length > 0) {
fs.writeFile(filePath, JSON.stringify(tour), function (err) {
if (err) {
if (callback) callback(err);
return console.error(err);
}
console.log("Tour Written: " + name);
});
} else {
console.error("Tour location empty: " + name);
}
}
var tour = this.prepareExport();
saveToFile(tour, callback);
};
schema.methods.prepareExport = function () {
// TODO: Ensure Track and POI are loaded
var tour = this.toObject();
var prevLeg = false;
// Calculate proper abs positions before prepare for export
for (li in tour.legs) {
var leg = tour.legs[li];
if (leg.ptuMode == 'poi') {
leg.ptu.pan.abs = leg.ptu.poi.pan;
leg.ptu.tilt.abs = leg.ptu.poi.tilt;
} else if (leg.ptuMode == 'rel' && prevLeg) {
leg.ptu.pan.abs = prevLeg.ptu.pan.abs + leg.ptu.pan.rel;
leg.ptu.tilt.abs = prevLeg.ptu.tilt.abs + leg.ptu.tilt.rel;
}
if (leg.ptuMode !== 'delay') {
prevLeg = leg;
}
}
// Calulcate degrees per second for each leg
prevLeg = false;
for (li in tour.legs) {
var leg = tour.legs[li];
if (prevLeg && leg.velMode == 'time') {
var time = Math.abs(leg.time) || 0;
if (time > 0) {
if (leg.ptuMode == 'delay') {
leg.ptu.delay = time;
} else if (leg.ptuMode == 'rel') {
leg.ptu.pan.vel = leg.ptu.pan.rel / time;
leg.ptu.tilt.vel = leg.ptu.tilt.rel / time;
} else {
leg.ptu.pan.vel = (leg.ptu.pan.abs - prevLeg.ptu.pan.abs) / time;
leg.ptu.tilt.vel = (leg.ptu.tilt.abs - prevLeg.ptu.tilt.abs) / time;
}
} else {
leg.ptu.pan.vel = 0;
leg.ptu.tilt.vel = 0;
}
leg.ptu.pan.vel = Math.abs(leg.ptu.pan.vel);
leg.ptu.tilt.vel = Math.abs(leg.ptu.tilt.vel);
if (leg.ptu.direction === 'ccw') {
leg.ptu.pan.vel = -leg.ptu.pan.vel;
}
// Vel bounds
if (leg.ptu.pan.vel > 50) {
leg.ptu.pan.vel = 50;
} else if (leg.ptu.pan.vel < 5 && leg.ptu.pan.vel > 0) {
leg.ptu.pan.vel = 5;
}
if (leg.ptu.tilt.vel > 50) {
leg.ptu.tilt.vel = 50;
} else if (leg.ptu.tilt.vel < 5 && leg.ptu.tilt.vel > 0) {
leg.ptu.tilt.vel = 5;
}
// Quickest was using 50ยบ/s, but should be omitted
if (leg.ptu.direction === 'quickest' && time === 0) {
delete leg.ptu.pan.vel;
delete leg.ptu.tilt.vel;
}
// Remove invalid tilt velocity when tilt diff is 0 so vector vel on control server is calculated correctly
if (prevLeg.ptu.tilt.abs - leg.ptu.tilt.abs == 0) {
delete leg.ptu.tilt.vel;
}
}
prevLeg = leg;
}
return tour;
};
/* bounds logic
if (leg.ptu.pan.abs > 180) {
leg.ptu.pan.abs = leg.ptu.pan.abs - 360;
} else if (leg.ptu.pan.abs < -180) {
leg.ptu.pan.abs = leg.ptu.pan.abs + 360;
}
if (leg.ptu.tilt.abs > 90) {
leg.ptu.tilt.abs = 90;
} else if (leg.ptu.tilt.abs < -90) {
leg.ptu.tilt.abs = -90;
}
*/
var Tour = mongoose.model("Tour", schema);
module.exports = Tour;
答案 0 :(得分:1)
您的异步功能出错:
schema.pre('save',function(next),next必须在回调函数中
tour.writeToFile(function (err) {
console.error(err);
next();
});
schema.methods.writeToFile = function(callback):您必须在成功时返回回调,而不仅仅是在错误
上 if (filePath && filePath.length > 0) {
fs.writeFile(filePath, JSON.stringify(tour), function (err) {
if (err) {
if (callback) callback(err);
return console.error(err);
}
else
{
console.log("Tour Written: " + name);
if (callback) callback(err);
}
});
} else {
console.error("Tour location empty: " + name);
if (callback) callback(err);
}