В последней версии HAPI.js есть некоторые изменения, на которые стоит обратить внимание. В YLD мы хотим быть как можно ближе к последним изменениям, и в этом блоге мы хотим немного рассказать о новой версии HAPI.js. Есть некоторые критические изменения, которые были созданы в основном из-за принятия async/await
.
Помните async/await
(Асинхронные функции)?
Если бы нам пришлось резюмировать async/await
в простом предложении, это было бы что-то вроде «Это делает все красивее, делая асинхронный код более читабельным». В следующем примере показана асинхронная функция, ожидающая выполнения обещания:
async function getById(id) {
try {
const item = await db.getById(id);
return item;
} catch(err) {
// deal with it (reject the promise)!
}
}
Небольшие заметки:
await
всегда ждет обещания (в этом случаеdb.getById
будет разрешено);await
можно использовать только внутриasync
функции (отсюда объявлениеasync function getById
);- вы можете использовать try / catch для выполнения обработки ошибок или придерживаться
then/catch
, предоставляемого обещаниями (есть также хорошие альтернативные решения, такие как apr-intercept или await-to-js); - это не упоминается в этом примере, но вы должны быть осторожны при вызове двух функций с использованием
await
внутри одной и той же функцииasync
. Если вы не справитесь с этим должным образом, вы можете получить серию кода, который можно запускать параллельно (подробности см. ВPromise.all
, или даже в утилите apr).
Но этот пост не о async/await
, давайте вернемся к HAPI.js! Чтобы получить больше информации о async/await
, ознакомьтесь с спецификацией ECMAScript или MDN.
Пока connections
Выполнять server.connection({ port: 3000 })
после создания сервера HAPI.js больше не требуется, чтобы быть в другой строке. Все методы из server.connection
теперь находятся в server
, и вы можете просто:
const Hapi = require('hapi');
const server = Hapi.server({ host: 'localhost', port: 3000 });
Используйте async/await
для запуска вашего сервера
Забудьте о функции обратного вызова в server.start
. Запустите его с помощью асинхронных функций:
async function start() { try { await server.start(); } catch (err) { console.error(err); process.exit(1); } };
start();
Забудьте об reply
интерфейсе
Вот и все, ответ был изменен на h
, что означает хапи. Теперь вы можете просто вернуть клиенту то, что хотите получить, или, если ваш ответ немного сложнее, вы можете использовать h.response
.
server.route({ method: 'GET', path:'/', handler: (request, h) => { return 'Hi, YLD!';
// ----> alternative: // const response = h.response('Hi, YLD!'); // response.code(200); // response.header('Content-Type', 'text/plain'); // return response; } });
s/config/options
Быстрый, быстрый. Замените config
на options
в своих маршрутах. Все остальное работает, как и раньше (например, payload
конфигурация и Joi
проверка), как вы можете проследить в этом фрагменте кода:
server.route({
method: 'POST',
path: '/users',
handler: createUser,
options: {
payload: {
allow: [ 'application/json' ]
},
validate: {
payload: {
name: Joi.string().required()
}
}
}
});
Зарегистрируйте плагин
В подпись плагина HAPI.js внесены изменения. Теперь он обозначает объект со следующими свойствами: { register, name, version, multiple, dependencies, once, pkg }
. Посмотрите здесь небольшой пример, где мы создаем простой yld-hapi-plugin.js
.
// inside our plugin (`yld-hapi-plugin.js`) const plugin = { register: (server, options) => { server.route({ method: 'GET', path:'/plugin', handler: (request, h) => { return 'Hi from a plugin'; } }); }, name: 'yld-hapi-plugin', version: '1.0.0' };
module.exports = plugin;
И, наконец, зарегистрируйте его в файле вашего сервера:
// inside my HAPI.js server
const YLDHapiPlugin = require('./plugins/yld-hapi-plugin.js');
/*...*/
await server.register(YLDHapiPlugin);
server.register
теперь возвращает обещание, но по-прежнему будет получать массив подключаемых модулей в качестве аргумента, так что await server.register([Inert, Vision, YLDHapiPlugin])
является действительным.
Серверные методы по-прежнему будут работать должным образом
Серверные методы - одна из самых интересных функций HAPI.js, а также полезный и эффективный способ совместного использования функций путем их присоединения к объекту сервера, вместо того, чтобы требовать наличия общего модуля везде, где это необходимо. Здесь нет больших различий, в следующем примере мы просто вызываем метод сервера add
, как и раньше, но с использованием нотации async/await
, где обратный вызов не требуется в качестве последнего аргумента при создании метода!
server.method('add', (a, b) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(a + b); }, 300); }); }, { cache: { expiresIn: 60000, generateTimeout: 1000 } });
server.route({ method: 'POST', path: '/add', handler: async (request, h) => { try { const result = await server.methods.add(1, 2); return result; } catch (err) { throw err; } } });
С async/await
приходит отскок!
bounce
- это модуль HAPI.js, который делает скрытые ошибки видимыми. Посмотрите следующий пример, в котором мы используем функцию Bounce.rethrow
. В этом случае b.c.d
может быть скрытой ошибкой (из-за try/catch
& async/await
), если bounce
не используется. Bounce позволяет фильтровать по system
и boom
ошибкам.
server.method('add', (a, b) => { return new Promise((resolve, reject) => { const a = b.c.d; reject('The line before should explode: ' + a); }); });
server.route({ method: 'POST', path: '/add', handler: async (request, h) => {
let result = null; try { result = await server.methods.add(1, 2); return result; } catch (err) { Bounce.rethrow(err, 'system'); } return result; } });
На этом пока все! Есть еще несколько незначительных изменений, но этот пост должен дать вам обзор и помочь вам начать переход на новую версию. Напишите нам в Twitter, если у вас есть вопросы или вы хотите узнать больше.
Опубликовано Даниэлой Матос де Карвалью (инженер-программист в YLD) в Инженерном блоге YLD