Reputation: 75
I'm afraid this might be a simple case of me completely misunderstanding how asynchronous works.
I'm working with the NPM module azure-storage. The problem I'm having is that the function appears to complete before the callback is executed. What's worse is that Azure Functions has some magic in that you "finish" your function by setting context.res
property.
They used to require you to call context.done()
but something changed from v1 to v2 and now I guess it's not that way anymore. But still, even if that were the case, the function would be ended before the call back executed.
What's worse is that my entity is not even being inserted but I can't tell why.
var azure = require('azure-storage');
var validate = require('validate.js');
var constraints = {
PartitionKey: {
presence: true,
email: true
},
description: {
presence: true
},
dueDate: {
presence: true
}
};
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
if (!(req.body && req.body.PartitionKey)
|| !(req.body && req.body.description)
|| !(req.body && req.body.dueDate)) {
context.res = {
status: 400,
body: "Please pass a name on the query string or in the request body"
};
}
var tableSvc = azure.createTableService();
var input = req.body;
context.log('PartitionKey: ' + input.PartitionKey);
context.log('description: ' + input.description);
context.log('dueDate: ' + input.dueDate);
context.log(validate({ PartitionKey: input.PartitionKey }, constraints));
context.log(validate({ description: input.description }, constraints));
context.log(validate({ dueDate: input.dueDate }, constraints));
var entGen = azure.TableUtilities.entityGenerator;
var task = {
PartitionKey: entGen.String(input.PartitionKey),
RowKey: entGen.String('1'),
description: entGen.String(input.description),
dueDate: entGen.DateTime(input.dueDate)
};
tableSvc.insertEntity('events', task, function (error, result, response) {
if (!error) {
// Entity inserted
context.log(result);
context.res = {
// status: 200, /* Defaults to 200 */
body: {
result: result,
response: response
}
};
}
else {
context.log(error);
context.res = {
status: 400, /* Defaults to 200 */
body: error
};
}
});
};
Upvotes: 0
Views: 196
Reputation: 1509
When exporting an async function, you can configure an output binding to take the return value. This is recommended if you only have one output binding. See doc
To assign an output using return, change the name property to $return in function.json.
{
"type": "http",
"direction": "out",
"name": "$return"
}
In this case, your function should look like the following example:
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
// You can call and await an async method here
return {
body: "Hello, world!"
};
}
This should work.
Your async function will not wait for the callback. You have to make it wait till the callback is finished.
var azure = require('azure-storage');
var validate = require('validate.js');
var constraints = {
PartitionKey: {
presence: true,
email: true
},
description: {
presence: true
},
dueDate: {
presence: true
}
};
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
if (!(req.body && req.body.PartitionKey)
|| !(req.body && req.body.description)
|| !(req.body && req.body.dueDate)) {
context.res = {
status: 400,
body: "Please pass a name on the query string or in the request body"
};
}
var input = req.body;
context.log('PartitionKey: ' + input.PartitionKey);
context.log('description: ' + input.description);
context.log('dueDate: ' + input.dueDate);
context.log(validate({ PartitionKey: input.PartitionKey }, constraints));
context.log(validate({ description: input.description }, constraints));
context.log(validate({ dueDate: input.dueDate }, constraints));
var entGen = azure.TableUtilities.entityGenerator;
var task = {
PartitionKey: entGen.String(input.PartitionKey),
RowKey: entGen.String('1'),
description: entGen.String(input.description),
dueDate: entGen.DateTime(input.dueDate)
};
let res = await tablework(task, context);
if(res.success) {
return {
status: 200,
body: {
result: res.result,
response: res.response
},
headers: {
'Content-Type': 'application/json'
}
};
}
else{
return {
status: 400, /* Defaults to 200 */
body: res.error,
headers: {
'Content-Type': 'application/json'
}
};
}
};
function tablework(task, context){
return (new Promise((resolve, reject) => {
var tableSvc = azure.createTableService();
tableSvc.insertEntity('events', task, function (error, result, response) {
if (!error) {
// Entity inserted
context.log(result);
resolve({
success: true,
result: result,
response: response
});
}
else {
context.log(error);
resolve({
success: false,
error: error
});
}
});
}));
}
Upvotes: 1