Reputation: 93
I have referenced so many solutions but I think my condition is quite different from what I have searched yet.
I am a newbie with async-await and promises.
I am creating a cron job function in nodeJS with MongoDB database.
I have a table named 'Device', in which I have a list of devices right now I have 5 records.
I have other tables mapped with the device table by deviceId i.e., 'Location', 'DeviceInfo', 'DailyStatus'.
Here is my code:
// schedule tasks to be run on the server every sec
cron.schedule("*/1 * * * * *", function() {
async function finalData() { //asyncronously final data
function findDevices() { //find all devices
return new Promise(function (resolve, reject) {
Device.find((error, data) => {
if (error) {
reject("error in sending the data");
} else {
if (data.length > 0) {
resolve(data); //get devices list successfully
} else {
reject("data length is ! > 0");
}
}
});
});
}
var dataNew = await findDevices().then(function (returnedData) {
console.log('every second','findDevices')
returnedData.forEach((element) => { //iteration perform properly
async function callMyData() {
var dataSpeed = await Location.findOne(
{ device: element.deviceId },
function (error, data) {
if (error) {
console.log('error',error)
return next(error);
} else {
return data.speed;
}
}
).sort({ _id: -1 });
console.log(dataSpeed.speed,'dataSpeed') //first
var dataIgnition = await DeviceInfo.findOne(
{ device: element.deviceId },
function (error, data) {
if (error) {
console.log('error',error)
return next(error);
} else {
return data.ignition;
}
}
).sort({ _id: -1 });
console.log(dataIgnition.ignition,'dataIgnition') //second
var dataDailyStatus = await DailyStatus.findOne(
{ device: element.deviceId },
function (error, data) {
if (error) {
console.log("error", error);
return next(error);
} else {
return data.status;
}
}
).sort({ _id: -1 });
console.log(dataDailyStatus.status,'dataDailyStatus') //third
}
return callMyData().then(function (string) {
console.log("next iteration"); //after every interation
});
});
});
}
finalData().then(function (string) {});
});
My cron is working fine and also getting the device records properly.
But I am not able to get the sequence of the records as per the requirement.
What I am expecting is:
every second findDevices
0 'dataSpeed'
0 dataIgnition
Idle dataDailyStatus
next iteration
0 'dataSpeed'
1 dataIgnition
Stop dataDailyStatus
next iteration
0 'dataSpeed'
1 dataIgnition
Idle dataDailyStatus
next iteration
0 'dataSpeed'
0 dataIgnition
Stop dataDailyStatus
next iteration
0 'dataSpeed'
1 dataIgnition
Idle dataDailyStatus
next iteration
Finished
What I actually get is:
every second findDevices
Finished
0 'dataSpeed'
0 'dataSpeed'
0 'dataSpeed'
0 'dataSpeed'
0 dataIgnition
0 'dataSpeed'
1 dataIgnition
1 dataIgnition
0 dataIgnition
1 dataIgnition
Idle dataDailyStatus
next iteration
Stop dataDailyStatus
Idle dataDailyStatus
Stop dataDailyStatus
next iteration
next iteration
next iteration
Idle dataDailyStatus
next iteration
Can you guys please help me out how I can achieve the requested sequence as I am quite new with async-await and promises.
Upvotes: 1
Views: 186
Reputation: 2452
You can get your desired result with simpler code.
I have rewritten finalData
with a library I created, rubico. rubico removes a lot of boilerplate surrounding Promises.
const { pipe, fork, tryCatch, switchCase, map, get, gt } = require('rubico')
const identity = x => x
const findDevices = () => new Promise((resolve, reject) => {
Device.find((err, data) => err ? reject(err) : resolve(data))
})
const getLocationByDeviceID = deviceId => new Promise((resolve, reject) => {
Location.findOne(
{ device: deviceId },
(err, data) => err ? reject(err) : resolve(data),
).sort({ _id: -1 })
})
const getDeviceInfoByDeviceID = deviceId => new Promise((resolve, reject) => {
DeviceInfo.findOne(
{ device: deviceId },
(err, data) => err ? reject(err) : resolve(data),
).sort({ _id: -1 })
})
const getDailyStatusByDeviceID = deviceId => new Promise((resolve, reject) => {
DailyStatus.findOne(
{ device: deviceId },
(err, data) => err ? reject(err) : resolve(data),
).sort({ _id: -1 })
})
const finalData = pipe([
tryCatch(
findDevices, // try findDevices()
() => { throw new Error('error in sending the data') }, // on error, throw a new Error
),
switchCase([
gt(get('length'), 0), identity, // if data length is greater than 0, send it through (x => x)
() => { throw new Error('data length is ! > 0') }, // else throw a new Error
]),
map(fork.series([ // for each device, log speed, ignition, dailyStatus in series
pipe([
get('deviceId'), // device => device.deviceId
getLocationByDeviceID, // deviceId => getLocationByDeviceID(deviceId) => location
get('speed'), // location => location.speed
x => console.log(x, 'dataSpeed')
]),
pipe([
get('deviceId'), // get device.deviceId
getDeviceInfoByDeviceID, // deviceId => getDeviceInfoByDeviceID(deviceId) => deviceInfo
get('ignition'), // deviceInfo => deviceInfo.ignition
x => console.log(x, 'dataIgnition')
]),
pipe([
get('deviceId'), // get device.deviceId
getDailyStatusByDeviceID, // deviceId => getDailyStatusByDeviceID(deviceId) => dailyStatus
get('status'), // dailyStatus => dailyStatus.status
x => console.log(x, 'dataDailyStatus')
]),
])), // [device] => [{ speed, ignition, status }]
])
cron.schedule('*/1 * * * * *', finalData)
Upvotes: 1