使用 callback/anonymous 函数迭代
Iterating with callback/anonymous functions
我是 Node.JS 和高级 Javascript 的新手,但我正在尝试自己构建一个日程管理器应用程序,但我遇到了一个问题(我稍后会详细说明) ) 尝试执行以下代码时:
router.get('/', function (req, res) {
var day = new Date(req.query.day);
Location.getLocations(function (err, locations) {
if (locations.length > 0) {
var i;
for (i = 0; i < locations.length; i++) {
var location = locations[i];
Appointment.getAppointments(day, location, function (err, appointments) {
if (err) throw err;
if (appointments.length == 0) {
// CREATE APPOINTMENTS
for (var j = location.available_time_start; j <= location.available_time_end; j += location.appointment_duration) {
var newAppointment = new Appointment();
newAppointment.start_date = new Date(day.getFullYear(), day.getMonth() + 1, day.getDate(), j);
newAppointment.appointment_duration = location.appointment_duration;
newAppointment.location = location.id;
newAppointment.booked = false;
newAppointment.locked = false;
Appointment.createAppointment(newAppointment, function (err, appointment) {
if (err) throw err;
console.log(appointment.location + ' - ' + appointment.start_date);
});
}
}
});
}
} else {
// THERE ARE NO LOCATIONS
}
res.render('appointments', { locations: locations });
});
问题是:
当我尝试迭代 locations
对象然后执行 getAppointments
函数时,代码并未在此时执行。后来,当它被执行时,location
对象总是相同的(迭代不起作用),导致意外的结果(所有约会都在 same/last 位置)。
我尝试使用 IIFE(立即调用的函数表达式)立即执行代码,但是当我这样做时我无法获得 appointments
回调对象并且我的逻辑也被破坏了。
提前致谢!
问题已通过使用 let
而不是 @JaromandaX 建议的 var
解决。
您的代码似乎在保存约会,但没有对保存的约会做任何事情(您在改变地点吗?)。
当保存约会出错时,请求者不知道它,因为 createAppointment
是异步的,并且在回调被回调时 res.render('appointments', { locations: locations });
已经执行。
您可以尝试将基于回调的函数转换为承诺:
const asPromise = (fn,...args) =>
new Promise(
(resolve,reject)=>
fn.apply(undefined,
args.concat(//assuming one value to resole
(err,result)=>(err)?reject(err):resolve(result)
)
)
);
const savedAppointmentsForLocation = (day,location,appointments) => {
const savedAppointments = [];
if (appointments.length == 0) {
// CREATE APPOINTMENTS
for (var j = location.available_time_start; j <= location.available_time_end; j += location.appointment_duration) {
var newAppointment = new Appointment();
newAppointment.start_date = new Date(day.getFullYear(), day.getMonth() + 1, day.getDate(), j);
newAppointment.appointment_duration = location.appointment_duration;
newAppointment.location = location.id;
newAppointment.booked = false;
newAppointment.locked = false;
savedAppointments.push(
asPromise(
Appointment.createAppointment.bind(Appointment),
newAppointment
)
);
}
}
//you are not doing anything with the result of the saved appointment
// I'll save it as promise to see if something went wrong to indicate
// to the requestor of the api that something went wrong
return Promise.all(savedAppointments);
}
router.get('/', function (req, res) {
var day = new Date(req.query.day);
asPromise(Location.getLocations.bind(Location))
.then(
locations=>
promise.all(
locations.map(
location=>
asPromise(Appointment.getAppointments.bind(Appointment),[day,location])
.then(appointments=>[location,appointments])
)
)
)
.then(
results=>//results should be [ [location,[appointment,appointment]],...]
Promise.all(
results.map(
([location,appointments])=>
savedAppointmentsForLocation(day,location,appointments)
.then(ignoredSavedAppointment=>location)
)
)
)
.then(locations=>res.render('appointments', { locations: locations }))
.catch(
error=>{
console.log("something went wrong:",error);
res.status(500).send("Error in code");
}
)
});
我是 Node.JS 和高级 Javascript 的新手,但我正在尝试自己构建一个日程管理器应用程序,但我遇到了一个问题(我稍后会详细说明) ) 尝试执行以下代码时:
router.get('/', function (req, res) {
var day = new Date(req.query.day);
Location.getLocations(function (err, locations) {
if (locations.length > 0) {
var i;
for (i = 0; i < locations.length; i++) {
var location = locations[i];
Appointment.getAppointments(day, location, function (err, appointments) {
if (err) throw err;
if (appointments.length == 0) {
// CREATE APPOINTMENTS
for (var j = location.available_time_start; j <= location.available_time_end; j += location.appointment_duration) {
var newAppointment = new Appointment();
newAppointment.start_date = new Date(day.getFullYear(), day.getMonth() + 1, day.getDate(), j);
newAppointment.appointment_duration = location.appointment_duration;
newAppointment.location = location.id;
newAppointment.booked = false;
newAppointment.locked = false;
Appointment.createAppointment(newAppointment, function (err, appointment) {
if (err) throw err;
console.log(appointment.location + ' - ' + appointment.start_date);
});
}
}
});
}
} else {
// THERE ARE NO LOCATIONS
}
res.render('appointments', { locations: locations });
});
问题是:
当我尝试迭代 locations
对象然后执行 getAppointments
函数时,代码并未在此时执行。后来,当它被执行时,location
对象总是相同的(迭代不起作用),导致意外的结果(所有约会都在 same/last 位置)。
我尝试使用 IIFE(立即调用的函数表达式)立即执行代码,但是当我这样做时我无法获得 appointments
回调对象并且我的逻辑也被破坏了。
提前致谢!
问题已通过使用 let
而不是 @JaromandaX 建议的 var
解决。
您的代码似乎在保存约会,但没有对保存的约会做任何事情(您在改变地点吗?)。
当保存约会出错时,请求者不知道它,因为 createAppointment
是异步的,并且在回调被回调时 res.render('appointments', { locations: locations });
已经执行。
您可以尝试将基于回调的函数转换为承诺:
const asPromise = (fn,...args) =>
new Promise(
(resolve,reject)=>
fn.apply(undefined,
args.concat(//assuming one value to resole
(err,result)=>(err)?reject(err):resolve(result)
)
)
);
const savedAppointmentsForLocation = (day,location,appointments) => {
const savedAppointments = [];
if (appointments.length == 0) {
// CREATE APPOINTMENTS
for (var j = location.available_time_start; j <= location.available_time_end; j += location.appointment_duration) {
var newAppointment = new Appointment();
newAppointment.start_date = new Date(day.getFullYear(), day.getMonth() + 1, day.getDate(), j);
newAppointment.appointment_duration = location.appointment_duration;
newAppointment.location = location.id;
newAppointment.booked = false;
newAppointment.locked = false;
savedAppointments.push(
asPromise(
Appointment.createAppointment.bind(Appointment),
newAppointment
)
);
}
}
//you are not doing anything with the result of the saved appointment
// I'll save it as promise to see if something went wrong to indicate
// to the requestor of the api that something went wrong
return Promise.all(savedAppointments);
}
router.get('/', function (req, res) {
var day = new Date(req.query.day);
asPromise(Location.getLocations.bind(Location))
.then(
locations=>
promise.all(
locations.map(
location=>
asPromise(Appointment.getAppointments.bind(Appointment),[day,location])
.then(appointments=>[location,appointments])
)
)
)
.then(
results=>//results should be [ [location,[appointment,appointment]],...]
Promise.all(
results.map(
([location,appointments])=>
savedAppointmentsForLocation(day,location,appointments)
.then(ignoredSavedAppointment=>location)
)
)
)
.then(locations=>res.render('appointments', { locations: locations }))
.catch(
error=>{
console.log("something went wrong:",error);
res.status(500).send("Error in code");
}
)
});