Вместо того, чтобы вручную преобразовывать каждую функцию обратного вызова в Promise, проще создать оболочку для поддержки асинхронного / ожидающего.
Ссылка
https://strongloop.com/strongblog/async-error-handling-expressjs-es7-promises-generators/
function asyncWrapper(fn) {
return (req, res, next) => {
return Promise.resolve(fn(req))
.then((result) => res.send(result))
.catch((err) => next(err))
}
}
Пример кода
async createUser(req) {
const user = await User.save(req.body)
return user
}
router.post('/users', asyncWrapper(createUser))
Рефакторинг вашего кода
function userGroup(type, zip) {
return new Promise(resolve => {
connection.query(`SELECT * FROM bt9.users WHERE zip = ${zip} AND type = ${type} AND display = 1`, function (err, result) {
if(err) throw err;
resolve(result);
});
});
}
async function getUsers({ type, zips }) {
let userList = [];
// [IMPORTANT]
// - Replaced the for-loop to for-of-loop for await to work.
// - This is not efficient because the `userGroup` function is run one by one serially.
for (let zip of zips) {
const users = await userGroup(type, zip);
userList = userList.concat(users);
}
return userList;
}
router.get('/:zipcode/:type/:rad', asyncWrapper(async (req) => {
const rad = req.params.rad;
const zip = req.params.zipcode;
let zips = zipcodes.radius(zip, rad);
zips.push(zip);
let type;
if(req.params.type === 'bartenders') {
type = 0;
} else {
type = 1;
}
return await getUsers({ type, zips });
}));
Чтобы еще больше повысить эффективность, вы должны заменить внутри петли внутри getUsers
на Promise.map
, предлагаемый bluebird .Promise.map
будет выполнять обещания параллельно.
async function getUsers({ type, zips }) {
let userList = []
const userListList = await Promise.map(zips, (zip) => {
return userGroup(type, zip);
});
for (let users of userListList) {
userList = userList.concat(users)
}
return userList;
}