Hello!
Total Koa newbie here, also new to the async/await syntax. In the post request below i was wondering how I can properly return the completed variable and attach it to ctx.body.
router.post('/resume', async (ctx) => {
await form.parse(ctx.req, (err, fields, files) => {
return sendMail(fields.candidateName, files.attachment)
.then((completed) => {
return completed;
});
});
})
router.post('/resume', (ctx) => {
return form.parse(ctx.req, (err, fields, files) => {
return sendMail(fields.candidateName, files.attachment)
.then((completed) => {
ctx.body = completed;
});
});
});
Alternatively, using async (like your code does):
router.post('/resume', async (ctx) => {
ctx.body = await form.parse(ctx.req, (err, fields, files) => {
return sendMail(fields.candidateName, files.attachment)
.then((completed) => {
return completed;
});
});
});
Thank you for the incredibly quick reply, @PlasmaPower. Unfortunately the first version gives me a 404 Not Found, and the second suggestion returns a 204 No Content.
The form.parse method comes from the multiparty library.
As for the sendMail function, it works like this:
export const sendMail = (candidateName, attachment) => {
return new Promise((resolve, reject) => {
transporter.sendMail({
from: emailAddress,
to: emailAddress,
subject: `Resume submission from ${candidateName}`,
text: `Resume submission from ${candidateName}`,
attachments: attachment
}, (err) => {
if (err) reject(err);
resolve('SENDING COMPLETE');
})
});
}
Thanks in advance for your investigation.
@rainesinternationaldev form.parse doesn't return it a promise from what I can tell. It seems to use an event based system. Try this:
router.post('/resume', (ctx) => {
ctx.body = '';
return new Promise((resolve, reject) => {
form.on('error', reject);
form.on('close', resolve);
form.parse(ctx.req, (err, fields, files) => {
sendMail(fields.candidateName, files.attachment)
.then((completed) => {
ctx.body += completed + '\n';
})
.catch((err) => {
ctx.body += 'ERROR: ' + err + '\n';
ctx.status = 500;
})
});
});
});
Wow you are brilliant, I hope you know that!
I had to place the reject and resolve handlers in the .catch and .then blocks, respectively, because apparently the events only fire when the _parsing_ completes; it does not care to wait until sendMail finishes. Otherwise it worked like a charm so I'll close this.
My question now is I thought a response was triggered the moment you assign ctx.body = '';. How does the route know to wait until the Promise is fulfilled?
@rainesinternationaldev Thanks! :) About the moving of reject and resolve - I'd be a bit careful about that as this will now error to the console if you have more than one upload in your form (as the Promise will resolve multiple times).
I thought a response was triggered the moment you assign ctx.body
Nope, a response is triggered when the returned promise resolves. Also, now you can just set ctx.body instead of appending to it as your code is for one upload only.
Most helpful comment
@rainesinternationaldev
form.parsedoesn't return it a promise from what I can tell. It seems to use an event based system. Try this: