Skip to content

Commit

Permalink
use promise instead of async await
Browse files Browse the repository at this point in the history
  • Loading branch information
chentsulin committed Aug 20, 2016
1 parent 45c4a13 commit ce0a0f0
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 9 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
lib
.nyc_output
benchmark/build
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
npm-debug.log
node_modules
lib
benchmark/build
119 changes: 119 additions & 0 deletions benchmark/run.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/* eslint-disable no-console */
/*
*
* node run.js 10
*
*/
const {
object,
string,
} = require('joi');
const async = require('./build/async').default; // eslint-disable-line import/no-unresolved
const promise = require('./build/promise').default; // eslint-disable-line import/no-unresolved

const schema = {
body: object().keys({
name: string().required(),
tel: string().required(),
addr: string().required(),
email: string().email().required(),
}),
};

const options = { stripUnknown: true };

const asyncMiddleware = async(schema, options);
const promiseMiddleware = promise(schema, options);

const ctx = {
request: {
body: {
name: 'CPH',
tel: '0912345678',
addr: '..',
email: 't@t.t',
},
},
};

const ROUND = +process.argv[2] || 100;

const format = (ms) => {
let remain = ms;
let formated = '';

formated = `${ms % 1000}ms`;
remain = Math.round(remain / 1000);
if (remain < 1) return formated;

formated = `${remain % 60}sec ${formated}`;
remain = Math.round(remain / 60);
if (remain < 1) return formated;

formated = `${remain % 60}min ${formated}`;
remain = Math.round(remain / 60);
if (remain < 1) return formated;

formated = `${remain % 24}hr ${formated}`;
remain = Math.round(remain / 24);
if (remain < 1) return formated;

formated = `${remain}day ${formated}`;
return formated;
};

console.log(`${ROUND} rounds to run..`);

const results = [[], [], []];

let p = Promise.resolve();

p.then(() => {
console.log('Start to run async function...');
});

for (let i = 0; i < ROUND; i++) {
let start;
p = p
.then(() => {
start = Date.now();
})
.then(() => asyncMiddleware(ctx, () => Promise.resolve()))
.then(() => {
results[0].push(Date.now() - start);
});
}

p.then(() => {
console.log('Start to run promise function...');
});

for (let i = 0; i < ROUND; i++) {
let start;
p = p
.then(() => {
start = Date.now();
})
.then(() => promiseMiddleware(ctx, () => Promise.resolve()))
.then(() => {
results[1].push(Date.now() - start);
});
}

p
.then(() => {
console.log(results[0].map(format));
const asyncSum = results[0].reduce((acc, next) => acc + next, 0);
console.log('async Average: ', format(asyncSum / ROUND));
console.log(results[1].map(format));
const promiseSum = results[1].reduce((acc, next) => acc + next, 0);
console.log('promise Average: ', format(promiseSum / ROUND));
console.log(results[2].map(format));
const fastAsyncSum = results[2].reduce((acc, next) => acc + next, 0);
console.log('fast-async Average: ', format(fastAsyncSum / ROUND));
process.exit(0);
})
.catch(err => {
console.error(err);
process.exit(1);
});
44 changes: 44 additions & 0 deletions benchmark/source/async.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { validate as _validate } from 'joi';
import thenify from 'thenify';

const validate = thenify(_validate);

export {
any,
alternatives,
array,
boolean,
binary,
date,
func,
number,
object,
string,
ref,
isRef,
} from 'joi';

function isContextOnlyKey(key) {
return key === 'params';
}

const validator = (schema, opts) => async (ctx, next) => {
const keys = Object.keys(schema);
for (let i = 0, len = keys.length; i < len; i++) {
const key = keys[i];
const source = isContextOnlyKey(key) ? ctx : ctx.request;
const validated = await validate( // eslint-disable-line no-param-reassign
source[key],
schema[key],
opts
);
Object.defineProperty(source, [key], {
get() {
return validated;
},
});
}
await next();
};

export default validator;
46 changes: 46 additions & 0 deletions benchmark/source/promise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { validate as _validate } from 'joi';
import thenify from 'thenify';

const validate = thenify(_validate);

export {
any,
alternatives,
array,
boolean,
binary,
date,
func,
number,
object,
string,
ref,
isRef,
} from 'joi';

function isContextOnlyKey(key) {
return key === 'params';
}

const validator = (schema, opts) => (ctx, next) => {
const keys = Object.keys(schema);
const promises = [];
for (let i = 0, len = keys.length; i < len; i++) {
const key = keys[i];
const source = isContextOnlyKey(key) ? ctx : ctx.request;
promises.push(validate(
source[key],
schema[key],
opts
).then(validated => {
Object.defineProperty(source, [key], {
get() {
return validated;
},
});
}));
}
return Promise.all(promises).then(() => next());
};

export default validator;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"scripts": {
"clean": "rimraf lib dist .nyc_output",
"build": "npm run clean && babel src -d lib --ignore __tests__",
"build:benchmark": "rimraf benchmark/build && babel benchmark/source -d benchmark/build",
"testonly": "NODE_ENV=test mocha $npm_package_options_mocha",
"test": "npm run lint && npm run testonly",
"test:cov": "nyc npm test",
Expand Down
20 changes: 11 additions & 9 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,25 @@ function isContextOnlyKey(key) {
return key === 'params';
}

const validator = (schema, opts) => async (ctx, next) => {
const validator = (schema, opts) => (ctx, next) => {
const keys = Object.keys(schema);
const promises = [];
for (let i = 0, len = keys.length; i < len; i++) {
const key = keys[i];
const source = isContextOnlyKey(key) ? ctx : ctx.request;
const validated = await validate( // eslint-disable-line no-param-reassign
promises.push(validate( // eslint-disable-line no-param-reassign
source[key],
schema[key],
opts
);
Object.defineProperty(source, [key], {
get() {
return validated;
},
});
).then(validated => {
Object.defineProperty(source, [key], {
get() {
return validated;
},
});
}));
}
await next();
return Promise.all(promises).then(() => next());
};

export default validator;

0 comments on commit ce0a0f0

Please sign in to comment.