From 5c15fa6ebf64dd4227d5ec68dd4c7dcc9ace67ed Mon Sep 17 00:00:00 2001 From: Patricio Diaz Date: Tue, 17 Sep 2019 16:15:02 -0400 Subject: [PATCH 1/2] Refactor to support Promises and Async/Await (WIP) Signed-off-by: Patricio Diaz --- .gitignore | 2 + template/node10-express/function/handler.js | 60 +++++++++++++++- template/node10-express/index.js | 77 +++++++++++---------- 3 files changed, 101 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index 32451fc..6f53e39 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ node_modules/** build + +template diff --git a/template/node10-express/function/handler.js b/template/node10-express/function/handler.js index a449950..c53348f 100644 --- a/template/node10-express/function/handler.js +++ b/template/node10-express/function/handler.js @@ -1,12 +1,66 @@ "use strict" -module.exports = (event, context) => { - let err; +// callback version +const delayCallback = cb => { + const min = 1; // 1 sec + const max = 5; // 5 sec + const delay = Math.round((Math.random() * (max - min) + min)); + setTimeout(() => cb(delay), delay * 1000); +} + +module.exports = (context, next) => { + console.log("handler/IN"); + + delayCallback(delay => { + const result = { + status: "You said: " + JSON.stringify(context.body), + delay + }; + + context + .status(200) + .succeed(result); + + next(); + }) +} + +// Uncomment the following line to use it in the promise or async/await versions +// const delayPromise = () => new Promise((resolve, reject) => delayCallback(delay => resolve(delay)) ) + +// Promise version +/* +module.exports = context => new Promise((resolve, reject) => { + delayPromise() + .then(delay => { + const result = { + status: "You said: " + JSON.stringify(context.body), + delay + }; + + context + .status(200) + .succeed(result); + + return resolve(context); + }) +}); +*/ + +// async/await version +/* +module.exports = async context => { + const delay = await delayPromise(); + const result = { - status: "You said: " + JSON.stringify(event.body) + status: "You said: " + JSON.stringify(context.body), + delay }; context .status(200) .succeed(result); + + return context; } +*/ \ No newline at end of file diff --git a/template/node10-express/index.js b/template/node10-express/index.js index 8c85f48..8a1ee41 100644 --- a/template/node10-express/index.js +++ b/template/node10-express/index.js @@ -14,70 +14,77 @@ app.use(bodyParser.raw()); app.use(bodyParser.text({ type : "text/*" })); app.disable('x-powered-by'); -class FunctionEvent { +class FunctionContext { constructor(req) { this.body = req.body; this.headers = req.headers; this.method = req.method; this.query = req.query; this.path = req.path; - } -} -class FunctionContext { - constructor(cb) { - this.value = 200; - this.cb = cb; - this.headerValues = {}; + this.statusCode = 200; + this.headerValues = {}; } status(value) { - if(!value) { - return this.value; + if (value) { + this.statusCode = value; } - this.value = value; return this; } headers(value) { - if(!value) { - return this.headerValues; + if(value && value.constructor === Object) { + this.headerValues = value; } - this.headerValues = value; - return this; + return this; } succeed(value) { - let err; - this.cb(err, value); + this.succeedValue = (isArray(value) || isObject(value)) ? JSON.stringify(value) : value; } - fail(value) { - let message; - this.cb(value, message); + fail(message) { + this.statusCode = 500; + this.failMessage = message; } } -var middleware = (req, res) => { - let cb = (err, functionResult) => { - if (err) { - console.error(err); - return res.status(500).send(err); - } +const middleware = (req, res) => { + let fnContext = new FunctionContext(req); + + const sendFail = () => { + res.status(500).send(fnContext.failMessage); + } - if(isArray(functionResult) || isObject(functionResult)) { - res.set(fnContext.headers()).status(fnContext.status()).send(JSON.stringify(functionResult)); - } else { - res.set(fnContext.headers()).status(fnContext.status()).send(functionResult); + const handleResult = result => { + if (fnContext.failMessage) { + sendFail() } - }; + else { + res.set(fnContext.headers).status(fnContext.statusCode).send(fnContext.succeedValue); + } + } + + let next = () => { + handleResult(fnContext); + } - let fnEvent = new FunctionEvent(req); - let fnContext = new FunctionContext(cb); + const result = handler(fnContext, next); - handler(fnEvent, fnContext, cb); + if (result instanceof FunctionContext) { + handleResult(result); + } + else if (result instanceof Promise) { + result + .then(asyncResult => handleResult(asyncResult)) + .catch(err => { + fnContext.fail(err); + handleResult(fnContext); + }) + } }; app.post('/*', middleware); @@ -98,4 +105,4 @@ let isArray = (a) => { let isObject = (a) => { return (!!a) && (a.constructor === Object); -}; +}; \ No newline at end of file From 1aff23d60d65722f088923130eccce63b6119a9b Mon Sep 17 00:00:00 2001 From: Patricio Diaz Date: Wed, 18 Sep 2019 14:51:43 +0000 Subject: [PATCH 2/2] Added back event parameter Signed-off-by: Patricio Diaz --- .gitignore | 2 +- template/node10-express/function/handler.js | 16 ++++++------ template/node10-express/index.js | 27 +++++++++------------ 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 6f53e39..c46c009 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ node_modules/** build -template +#template diff --git a/template/node10-express/function/handler.js b/template/node10-express/function/handler.js index c53348f..d005d30 100644 --- a/template/node10-express/function/handler.js +++ b/template/node10-express/function/handler.js @@ -8,12 +8,10 @@ const delayCallback = cb => { setTimeout(() => cb(delay), delay * 1000); } -module.exports = (context, next) => { - console.log("handler/IN"); - +module.exports = (event, context, next) => { delayCallback(delay => { - const result = { - status: "You said: " + JSON.stringify(context.body), + const result = { + status: "You said: " + JSON.stringify(event.body), delay }; @@ -30,11 +28,11 @@ module.exports = (context, next) => { // Promise version /* -module.exports = context => new Promise((resolve, reject) => { +module.exports = (event, context) => new Promise((resolve, reject) => { delayPromise() .then(delay => { const result = { - status: "You said: " + JSON.stringify(context.body), + status: "You said: " + JSON.stringify(event.body), delay }; @@ -49,11 +47,11 @@ module.exports = context => new Promise((resolve, reject) => { // async/await version /* -module.exports = async context => { +module.exports = async (event, context) => { const delay = await delayPromise(); const result = { - status: "You said: " + JSON.stringify(context.body), + status: "You said: " + JSON.stringify(event.body), delay }; diff --git a/template/node10-express/index.js b/template/node10-express/index.js index 8a1ee41..3c6f1fe 100644 --- a/template/node10-express/index.js +++ b/template/node10-express/index.js @@ -14,14 +14,20 @@ app.use(bodyParser.raw()); app.use(bodyParser.text({ type : "text/*" })); app.disable('x-powered-by'); -class FunctionContext { +let isObject = a => !!a && (a.constructor === Object); + +class FunctionEvent { constructor(req) { this.body = req.body; this.headers = req.headers; this.method = req.method; this.query = req.query; this.path = req.path; + } +} +class FunctionContext { + constructor() { this.statusCode = 200; this.headerValues = {}; } @@ -43,7 +49,7 @@ class FunctionContext { } succeed(value) { - this.succeedValue = (isArray(value) || isObject(value)) ? JSON.stringify(value) : value; + this.succeedValue = (Array.isArray(value) || isObject(value)) ? JSON.stringify(value) : value; } fail(message) { @@ -53,7 +59,8 @@ class FunctionContext { } const middleware = (req, res) => { - let fnContext = new FunctionContext(req); + let fnEvent = new FunctionEvent(req); + let fnContext = new FunctionContext(); const sendFail = () => { res.status(500).send(fnContext.failMessage); @@ -68,11 +75,9 @@ const middleware = (req, res) => { } } - let next = () => { - handleResult(fnContext); - } + let next = () => handleResult(fnContext); - const result = handler(fnContext, next); + const result = handler(fnEvent, fnContext, next); if (result instanceof FunctionContext) { handleResult(result); @@ -98,11 +103,3 @@ const port = process.env.http_port || 3000; app.listen(port, () => { console.log(`OpenFaaS Node.js listening on port: ${port}`) }); - -let isArray = (a) => { - return (!!a) && (a.constructor === Array); -}; - -let isObject = (a) => { - return (!!a) && (a.constructor === Object); -}; \ No newline at end of file