Обробка POST запиту в окремому файлі Nodejs+express
Доброго дня.
Допоможіть мені трішки, я справді перерив інтернет і не можу знайти відповідь. Пишу для себе пет-проект на Nodejs+express. Сайт з новинами, коментарями і все таке, все по стандарту. Вже зробив шаблон, формочки входу, додавання коментарів, вивід новин з БД і внесення новин в БД. Але всі форми у мене обробляються в app.js. Виглядає все якось так.
У мене є певна форма, вона міститься в файлі з розширенням ejs.
<form action="/form" method="POST"> <input type="text" name="first_name"/> <input type="submit" value="Send"/> </form>
Код котрий її обробляє, знаходиться в файлі app.js
app.post('/form', function(req, res, next){
код обробки форми, котрий заносить дані в БД
});
Все чудово працює.
Якщо таких форм буде
Спасибі велике за увагу.
46 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарівЩе хочу спитати, така проблема була і раніше. Результат обробки запиту і те що було занесену в БД, я можу побачити зупинивши мій сайт і знову запустивши. Просто оновити сторінку не допомагає. Як це вирішити? Що пошукати і що почитати? Буду дуже вдячний за допомогу.
БД у вас яка, MySQL? Без коду вставки даних в БД важко сказати «що не так».
Так, MySQL.
ejs файл шаблону цієї сторінки, не весь звісно, а кусок з формою та виводом існуючих коментарів.файл js сторінки з формою і виводом коментарів.
вміст файла обробника форми
частинка app.js, підключення обробника форми
Спасибі Вам, за те що приділяєте увагу.
Справа в тому, що Node.js не працює так як PHP — не перечитує за кожним запитом увесь ланцюжок директив. За кожним запитом обробляються лише так звані middleware рівня застосунку, або рівня роутинга, почитайте документацію з цього приводу.
В даному випадку краще зробити спеціальну функцію, яка буде спрацьовувати при кожному запиті роутера:
function getText() { var text = ''; con.query('SELECT * FROM Comments', function (err, rows, next) { if (err) throw err; for (i = 0; i < rows.length; i++) { text += ` <div id="page_container"> <div id="page_content"> ${rows[i].comment} </div> </div>` } }); } router.get('/', function(req, res, next) { res.render ( comments, { title: 'site title', com: getText() } ); });P.S. І зверніть увагу на лапки, в які я взяв текст, — node.js вже розуміє `отакі лапки`, забудьте про багаторядкову конкатенацію, типу ’текст ’ + ’ще якийсь текст’.
У мене, тепер просто коментарі не виводяться. Спочатку писало comments undefined — матюкається на те, що знаходиться в рес.рендер. Я додав лапки, але таким чином взагалі не виводяться коментарі, але працює сторінка і не призводить до помилки. До речі, те що вноситься в title — спрацьовує, також коментар додається. Перевіряв відкатом змін і перзапуском.
Так, як і написав нижче Артем, я і сам не врахував асинхронність (теж покищо лише вчусь писати під Node.js).
По-ідеї, змінювати тут не потрібно багато чого. Тут я двічі використав middleware router.get(’/’). Результат виконання передав у змінну res, тобто у змінну відповіді, після чого ловлю цей результат в наступному middleware.
Спробуйте, тепер здається повинно працювати.
router.get('/', function (req, res, next) { var text = ''; con.query('SELECT * FROM Comments', function (err, rows, next) { if (err) throw err; for (i = 0; i < rows.length; i++) { text += ` <div id="page_container"> <div id="page_content"> ${rows[i].comment} </div> </div>` } res.comments = text; next(); }); }); router.get('/', function(req, res, next) { res.render ( comments, { title: 'site title', com: res.comments } ); });Я покищо працював лише із Restify, його плагіни-middleware викликають next() самостійно, я подумав що і у Express так само. Тим більше — цей код я не змінював, автор каже що у нього виводиться інфа.
Стосовно
автор модуля MySQL наводить приклад коду, де немає next();github.com/...
Ну ок, а кто вызывает next когда вы бросаете тут исключение?
Я починаю думати, що ця технологія для тривіальних задач типу сайт візитка чи щось в цьому роді — геть не підходить. Так наче просто не підходящий інструмент. Але розбираюсь далі, поки відклав цю задачу з перечитування ще раз файлу або запиту в БД на вибірку. Є ще ціла купа речей котрих потрібно осягнути.
А, так — може бути, то вже деталі які уточнюються «на місці». Я просто не працюю з в’юхами (видаю відповідь у вигляді JSON).
В попередньому коді я забув ще й закрити MySQL-з’єднання. Може вже це працюватиме:
router.get('/', function (req, res, next) { var text = ''; var con = sql.createConnection({ // тут дані про базу }); con.query('SELECT * FROM Comments', function (err, rows, fields) { if (err) throw err; for (i = 0; i < rows.length; i++) { text += ` <div id="page_container"> <div id="page_content"> ${rows[i].comment} </div> </div>` } res.comments = text; next(); }); con.end(); }); router.get('/', function(req, res, next) { res.render ( 'comments', { title: 'site title', com: res.comments } ); });Артем, якщо автор модуля MySQL для Node.js не дописує next(), значить він передає таку err, яка сама прибиває завислі запити.
Я про HTTP-запрос говорю, который вы обрабатываете. Модуль mysql не знает и не должен знать о том, какие http запросы сейчас выполняются и что с ними делать в случае ошибки.
Ви маєте на увазі треба зробити так?
if (err) { next(); throw err; }Мені здається директива next() не повинна викликатись тут. В мене в цьому плані мало досвіду, думаю що правильним завершенням запиту повинен займатись все ж обробник помилок.
Запустите код и скажите, что происходит, если при выполнении SQL происходит ошибка.
У Restify, MySQL-помилка видається у відповіді клієнту (без додаткового next() у тілі обробки запиту ).
Я вам просто безмежно вдячний, ось, воно працює ;-) Порадьте, будь ласка, ресурси чи книги по котрим ви вивчаєте ноду.
Почему я вижу РНР и не вижу JS?
А можна побачити, як би це написав Senior JavaScript Developer. Тільки не подумайте, що я пишу заради жарту. Я дійсно був би дуже радий, побачити як пишуть це JSсівці зі стажем. А то я, як і Костя Третяк, мислю по PHPшному
не, я тут код писать не буду, я его и так много пишу в других местах
Ви про такий код говорите (щоправда — це TypeScript, але думаю це не суттєво)?
import {MysqlConnectService} from '../services/mysql-connect-service'; import {Inject, annotate} from 'di'; interface IUser { id:number ,userName:string ,userEmail:string } export class UsersModel { constructor(private connect:MysqlConnectService){} getConnection() { return this.connect.getConnection(); } getListUsers = ():Promise<IUser[]> => { let connection = this.getConnection(); return new Promise( (resolve, reject) => { connection.query('select id, userName, userEmail from users', (err, rows, fields) => { if(err) reject(err); else resolve(rows); }); connection.end(); }) } } annotate(UsersModel, new Inject(MysqlConnectService));плюс минус
Потому что это PHP, написанный на JS
Ну я догадувався, що ви очікували Promise в коді, але схоже що для автора теми вивчення промісів ще попереду.
Такий код схвалюєте? dou.ua/... orums/topic/17844/#949210
І ще одне — ви не правильно очікуєте next у запиті до БД
con.query('SELECT * FROM Comments', function (err, rows, next)Правильно будеcon.query('SELECT * FROM Comments', function (err, rows, fields)Может лучше написать на PHP?
Я, особисто, радий писати на PHP, і з задоволенням продовжував писати на ньому. Але річ у тім, що керівництво вважає, що node.js, це гіпермегасуперкрута офігіти яка потужна мегаасинхронна штука, котра дозволяє робити все на світі. А нею потрібно клепати сайти, а PHP рівносильно Воланд де Морту, в тому сенсі, що ім’я згадувати не можна ;-) Ось і я переучуюсь і намагаюсь освоїти.
Вызывается getText, который асинхронно запускает SQL запрос и не возвращает никакого результата (undefined). Этот undefined кладется в объект, который отправляется на рендеринг.
После этого SQL запрос завершает выполнение, идет считывание результатов и собирание их в строку (вот тут возникает вопрос на чем все-таки пишет автор — на ноде или на PHP), но этот результат уже никуда не попадает.
Попробуйте вот так github.com/zmts/expressjs-base или так github.com/... mts/expressjs-experiments если будет удобно
Смысл, вынести роутер и контроллеры в отдельные файлы
Эээх... Новички уже превращают ДОУ в форум для себя :( Таких форумов есть полно. В частности по javascript, и около него
forum.jscourse.com
Можливо причина в тому, що новачки сприймають жителів цього форму, як мудрих і всезнаючих людей?))
Ви так написали, наче можете чітко означити тематику ДОУ. Яка вона? — Як ми створили Стартап? — Сири по 500 грн.? Чи може “куда бы свалить”? Або “как найти девушку Java-джуниору”?
У мене все видавало помилки(( Хоча інші просто файли в зв’язці ejs+js правильно роутив. В результаті рішення по виносу в окремий файл обробки форми, за межі app.js було зроблене створенням модуля. Навчився як їх робити.
файл модуля.
var sql = require(’mysql’);
var con = sql.createConnection({
host: «localhost»,
user: «user»,
password: «password»,
database: «a3b»
});
module.exports.formHandler = function(req, res, next) {
var message = {id_Source: 1, id_User :’1′, comment: req.body.comment};
var query = con.query(’INSERT INTO Comments SET ?’, message, function(err, result) {
});
console.log(query.sql);
res.redirect(301, ’http://localhost:4006′);
};
Ще хочу спитати, така проблема була і раніше. Результат обробки запиту і те що було занесену в БД, я можу побачити зупинивши мій сайт і знову запустивши. Просто оновити не допомагає. Як це вирішити? Що пошукати і що почитати?Буду дуже вдячний за допомогу.
почему он должен быть большим? Почему вы для 30 форм будете использовать 1 action. Это как минимум странно
Во-вторых, там не может быть много кода, потому что большая часть логики уходит в модели, layouts, blocks кароче размазывается ровным словом говна по всем паттернам
Для 30ти форм (число умовне) не один action, а різні. Просто подумав, що пхати всі обробники в головний файл не добре. Можу помилятись.
Цікаво чи використовували ви генератор коду. Там же показано як організувати і структуру роутінгу:
Чи вам таке не підходить?Підходить, у мене правда не джейд, а єджиес. Але то в даному прикладі ролі не грає. Спасибі за наведення, з згенерованим кодом тримав відповіді на багато питань.
express.Router в помощь.
Вынеси функции обработки запросов в отдельные файлы, а в app.js используй их.
var form = require('./routes/form'); ... app.use('/form', form);expressjs.com/en/guide/routing.html
Вы можете вынести функции обработки разных запросов в отдельный файл и require-ить их в app.js, тогда у вас app.js по сути будет роутингом, и будет что-то вроде:
const formHandler = require('...'); app.post('/form', formHandler);можно попробовать еще import если es6 поддерживается в проекте
Node v6.2.2 пока import не поддерживает. import это вообще es7 по-моему, в es-6 он только представлен.
а ок, я давно с нодой не работал, думал уже поддерживает
Спасибі за відповідь. Тобто вирізаю все що було раніше в app.post(’/form’, function(req, res, next){
код обробки форми, котрий заносить дані в БД
}); обрамляю в файлі все це в функцію і підключаю через require як і інші файли мого проекту?
Да, но выносить можно не тело функции и вызывать ее внутри callback-а, а саму функцию, и передавать ее как callback вторым параметром в app.post. Также обратите внимание на комментарий Костя Третяк, возможно он натолкнет на правильную структуру приложения в целом.