How to conditionally skip a promise and do nothing. I have created a nested promise, by which i have 7 .then's. But conditionally, i need to skip few .then and do nothing in that block, how to achive this ?
My FULL CODE:
const admin = require('firebase-admin');
const rp = require('request-promise');
module.exports = function(req, res) {
const phone = String(req.body.phone).replace(/[^\d]/g, '');
const amount = parseInt(req.body.amount);
const couponCodeName = (req.body.couponCodeName);
const couponUsage = parseInt(req.body.couponUsage);
const usersCouponUsage = parseInt(req.body.usersCouponUsage);
const finalAddress = (req.body.finalAddress);
const planName = (req.body.planName);
const saveThisAddress = (req.body.saveThisAddress);
const orderNumber = (req.body.orderNumber);
const pay_id = (req.body.pay_id);
const options = {
method: 'POST',
uri:`https://..........`,
body: {
amount
},
json: true
};
return admin.auth().getUser(phone)
.then(userRecord => {
return rp(options)
})
.then((orderResponse) => {
return admin.database().ref('trs/'+ phone)
.push({ pay_id: orderResponse.id })
})
.then(() => {
return admin.database().ref('ors/'+ phone)
.push({ pay_id })
})
.then(() => {
return saveThisAddress === true ?
admin.database().ref('address/'+phone)
.push({address: finalAddress}) : null
})
.then(() => {
return admin.database().ref('deliveryStatus/'+phone+'/'+orderNumber)
.set({ plan: planName === "" ? "Single Day Plan" : planName, delivered: false}, () => {
res.status(200).send({ success:true })
})
})
.then(() => {
return couponCodeName === "" ? null :
admin.database().ref(`couponCodes/${couponCodeName}`)
.update({couponUsage: couponUsage + 1 })
})
.then(() => {
return usersCouponUsage === "" ? null :
admin.database().ref(`couponUsage/${phone}`)
.update({ [couponCodeName]: usersCouponUsage + 1 })
})
.catch((err) => {
res.status(422).send({ error: err })
})
.catch((err) => {
res.status(422).send({error: err });
});
}
From the above code, last two .then has a condition return couponCodeName === "" ? null : code... )}.
What i need to achieve is, when the couponCodeName === "" then, it should skip the .then block and do nothing. But, i am returning null in this, it throws an unhandled rejection error. So how to achieve this ? How to skip a .then, and do nothing ( Its important to do nothing, simply skip it ) How to do this ?
THE ERROR I AM GETTING IS: The error i am getting from these nested .then is "Unhandled rejection" & "Error: Can't set headers after they are sent."
Error From Google Cloud Function
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:369:11)
at ServerResponse.header (/var/tmp/worker/node_modules/express/lib/response.js:767:10)
at ServerResponse.send (/var/tmp/worker/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/var/tmp/worker/node_modules/express/lib/response.js:267:15)
at ServerResponse.send (/var/tmp/worker/node_modules/express/lib/response.js:158:21)
at admin.auth.getUser.then.then.then.then.then.then.then.catch.catch (/user_code/request_payment_details.js:86:28)
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
And also
Unhandled rejection
Note: Node Js version : 6 ( So i think officially , i cant use async and await )
Conditional execution controls whether or not the core will execute an instruction. Most instructions have a condition attribute that determines if the core will execute it based on the setting of the condition flags.
In order to write useful programs, we almost always need the ability to check conditions and change the behavior of the program accordingly. Conditional statements give us this ability. The simplest form is the if statement: if x > 0 : print('x is positive')
if statements are used to conditionally execute statement lists according to the value of a boolean expression. In this form, the if keyword is followed by a boolean expression, the keyword then, a list of statements and the final keyword end.
There is no limit on the number of statements that can appear under the two clauses of an if else statement, but there has to be at least one statement in each block. Occasionally, it is useful to have a section with no statements (usually as a place keeper, or scaffolding, for code you haven't written yet).
Maybe you can use async/await
for this, as synchronization is what you need:
async function doSomething() {
var res1 = await promise1();
if (res1 === xxx) {
var res2 = await promise2();
} else {
...
}
}
Part 1: Your error handler should not crash.
If you call res.status(200)
, Express starts streaming data to the client (the headers are already sent). You can't change the response status afterwards with res.status(500)
, as the status code is already on its way to the client.
stuff()
.then(result => {
res.status(200).send(result); // server starts sending
}).then(moreStuff) // error occurs here
.catch(error => {
res.status(500).send(error); // fails, as server is already sending
});
To resolve this, you should only start streaming any data when all of your tasks are done:
stuff().then(moreStuff).then(evenMoreStuff) // error occurs here
.then(result => {
res.status(200).send(result); // doesnt get executed
}).catch(error => {
console.error(error);
res.status(500).send("Whoops, server error\n" + error.message); // works
});
Part 2: The logic inside your error should not throw at all.
Now that the error handler works correctly you should be able to find out what's actually going wrong in your code.
(We can't help you with that without a proper error message)
Part 3: Implement the wanted conditional execution:
To conditionally execute promises, you have to nest them:
a().then(() => {
if(!stuff) return; // exit early, continue at next then
return b().then(c); // conditionally execute b and c
}).then(rest); // executes after b and c if stuff is true
Part 4: Now that everything is working, you could refactor your code to async
/ await
to make it way more readable:
As you pointed out, v6 dpes not support async
/ await
, you'd have to you migrate to v8 or you transpile it down with webpack:
module.exports = async function(req, res) {
try {
//...
const userRecord = await admin.auth().getUser(phone);
const orderResponse = await rp(options)
await admin.database().ref('trs/'+ phone)
.push({ pay_id: orderResponse.id });
await admin.database().ref('ors/'+ phone)
.push({ pay_id })
if(saveThisAddress === true) {
await admin.database().ref('address/'+phone)
.push({address: finalAddress});
}
await admin.database().ref('deliveryStatus/'+phone+'/'+orderNumber)
.set({ plan: planName === "" ? "Single Day Plan" : planName, delivered: false});
if(couponCodeName !== "") {
await admin.database().ref(`couponCodes/${couponCodeName}`)
.update({couponUsage: couponUsage + 1 });
}
if(usersCouponUsage !== "") {
await admin.database().ref(`couponUsage/${phone}`)
.update({ [couponCodeName]: usersCouponUsage + 1 });
}
res.status(200).send({ success:true });
} catch(error) {
console.error("Error inside API", error);
res.status(422).send({ error });
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With