LINUX.ORG.RU

Javascript + fetch = Node.js

 , ,


0

1

Доброго всем дня!

Решаю следующую задачу: на HTML-странице, использующей css и javascript (естественно все файлы расположены в любой папке на клиенте) необходимо, в зависимости от введённой пользователем информации, записать значения полей в текстовой файл, чтобы потом при открытии этой страницы - можно было данные подгрузить и считать, а не набирать заново.

Девелоперы (я - не они) подсказали, чтобы я забыл об этом и думал в сторону Node.js. Ну я подумал и решил протестить решение. В результате чего, на той машине, где HTML-страница был установлен и запущен Node.js в режиме Express со всеми нужными модулями.

Сервер Node.js express работает.

Но, сервер не может получить от клиента данные в виде json.

Прочитал официальные данные с сайта (например эти: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) и аккуратно в javascipt’е готовлю данные для вызова fetch. И как бы я данные не подготавливал - Node.js постоянно в функции app.post(‘/data’, function(request, response) получает в request.body данные в виде undefined.

Я заморочился и снифером поймал пакеты от клиента к серверу и обратно и увидел, что как бы на клиенте я старательно не готовил поле Content-Type в значение application/json, но в пакете HTTP в сторону сервера упорно присутcтвует знвчение text/plain для Content-Type. Я полагаю, что именно здесь, роется причина того, что сервер не может принять данные от клиента.

Хотя-мне json в принципе и не нужен - нужно просто передавать строку на сервер для записи в файл, но насколько я понимаю при общении с Node.js нужно обязательно использовать json.

Подскажите пожалуйста, что username делает не так и как можно спасти отца русской демократии от неминуемого провала?

Спасибо.

Ответ на: комментарий от skyman

Да, про localstorage рассматривался вариант, но мне не понятно подходит ли он, если нужно разные вводимые пользователем данные сохранять под разные задачи. Например, один раз - данные нужны для проекта А, а в другой раз - для проекта Б.

Ramirezkiv2
() автор топика
Ответ на: комментарий от vbr

Содержимое обработчика нажания кнопки на форме для отправки тестовых данных на сервер Node.js:

async function SaveConfigMenu_onclick() {

const myOptions = {
  mode: "no-cors",
  method: "POST",
  headers: {
    "Content-Type": "application/json; charset=UTF-8",
  },
  body: JSON.stringify({
    name: "Gurav",
    age: 42
  })
};
	
await fetch('http://localhost:3000/data', myOptions)
  .then((response) => response.json())
  .then((json) => console.log(json));
} 

Содержимое файла app.js, на стороне Node.js:

const express = require('express')
const bp = require('body-parser')
const app = express()
const port = 3000

app.use(bp.json());
//app.use(bp.urlencoded({extended: true}));

app.get('/', (req, res) => {
	console.log("req.body = "+req.body)
    res.send('Nodejs answer is Hello World!')
})

app.post('/data', function(request, response){
    console.log("Data accepted from Client");      // your JSON
    response.setHeader('Content-Type', 'application/json')
    response.write('you posted:\n')
	response.end(String(JSON.stringify('{"hello":"world"}')))
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})
Ramirezkiv2
() автор топика
Ответ на: комментарий от skyman

Хммм! Надо будет попробовать. Подскажите, физическое расположение localstorage в файловой системе - одно, на всю систему или в зависимости от папки, в которой находится HTML-страница? Ну то есть, для проекта А - я делаю папку «Проект А» и запуская оттуда HTML и сохраняя значения нужных данных сохранение будет идти в этой папке, а для проекта Б - в папке «Проект Б»?

Ramirezkiv2
() автор топика
Ответ на: комментарий от Ramirezkiv2

В режиме no-cors браузер разрешает Content-Type только application/x-www-form-urlencoded, multipart/form-data, или text/plain.

Ещё в ответе с сервера должен быть валидный json без you posted:\n, иначе fetch.json() не сможет распарсить.

anonymous
()
16 июня 2025 г.
Ответ на: комментарий от Ramirezkiv2

Тебе не нужен no-cors, если ты не знаешь, зачем он тебе нужен. А при отправке ответа не надо отправлять «you posted:», только сам JSON.stringify (и пропускать через String тоже не надо, stringify достаточно).

KivApple ★★★★★
()
8 марта 2026 г.
Ответ на: комментарий от Ramirezkiv2

Спасибо конечно. Нервно вспоминаю. Я доделал, на клиенте ввожу значения json переводит на сервер там счёт полученные данные через json обратно на клиента на сервере node.js

saufesma
()
Ответ на: комментарий от saufesma

Ну здорово, что так!

Тогда на всякий случай всё же приведу здесь код серверной стороны и клиентской, чтобы если кто будет просматривать тему смог воспользоваться рабочей конфигурацией и кодом. Может быть сам вернусь к этой теме через некоторое время. ПС: решил задачу не с использованием localstorage.

Серверная сторона. Содержит код запуска сервера на порту TCP/3000 (можно поменять на любой не занятый порт в системе до 65535), а также два обработчика события - loadconfig и saveconfig.

Обработчик loadconfig загружает на клиента из заранее сохранённого текстового файла на стороне сервера - сохранённую конфигурацию (можно открыть текст и посмотреть, что там формат JSON), а обработчик saveconfig сохраняет переданные клиентом текстовые данные на серверную сторону в текстовый файл.

Содержимое файла серверной стороны c:\Users\User\Nodejs\nodejs-kits.js (название файла придумал сам и содержимое вымучал по форумам и манам):

const express = require('express')
const bp = require('body-parser')
const cors = require('cors')
const app = express()
const port = 3000
const options = { 
	inflate: true, 
	limit: 100000, 
	defaultCharset: 'utf-8' 
}; 
const fs = require('node:fs');
const lineReader = require('line-reader');

app.use(bp.text(options));
app.use(cors());

app.get('/', (req, res) => {
	console.log("req.body = "+req.body)
	res.send('Nodejs answer is Hello World!')
})

app.post('/loadconfig', function(request, response){
	console.log("Data accepted from Client"); // your JSON
	console.log("requst.body = "+request.body)
	let text = request.body;
	let myJson = JSON.stringify(text)
	console.log("json= "+myJson)
	
	fs.readFile('C:\\Users\\user\\Nodejs\\Project1_itobjects.kits', 'utf8', (err, data) => {
		if (err) {
			console.error(err);
		} else {
			console.log(data);
			response.setHeader('method', 'POST');
			response.setHeader('Content-Type', 'text/plain');
			response.send(data);
		}
	});
			
});

app.post('/saveconfig', function(request, response){
	console.log("Data accepted from Client"); // your JSON
	console.log("requst.body = "+request.body)
	let text = request.body;
	console.log("JSON.stringify(text) = "+text)
	
	fs.writeFile('C:\\Users\\user\\Nodejs\\Project1_itobjects.kits', text, 'utf8', err => {
		
		if (err) {
			console.error(err);
		} else {
			console.log("Writed to file successfully!");
			response.setHeader('method', 'POST');
			response.setHeader('Content-Type', 'text/plain');
			response.send('Config saved successfully!');
		}
	
	});		

});

app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})

Теперь куски содержимого .js-файла на клиентской стороне:

async function LoadConfigMenu_onclick() {

	var USER_LOC_body = "load_config";

	const myOptions = {
		mode: "cors",
		method: "POST",
		headers: {
			'Content-Type': 'text/plain; charset=UTF-8'
		},
		body: USER_LOC_body
	};
	
	let response = await fetch('http://localhost:3000/loadconfig', myOptions);
	
	console.log(response.headers.get('Content-Type'));
	
	let USER_LOC_text = await response.text();
	
	console.log(USER_LOC_text);	
	
	var USER_LOC_obj = JSON.parse(USER_LOC_text);

        ///Обращения к переменной USER_LOC_obj так как нужно
...

}


async function SaveConfigMenu_onclick() {
	
	var USER_LOC_body = "";

	USER_LOC_body = JSON.stringify(USER_GL_SuperClass);
	
	console.log("USER_LOC_body = "+USER_LOC_body);
	
	const myOptions = {
		mode: "cors",
		method: "POST",
		headers: {
			'Content-Type': 'text/plain; charset=UTF-8'
		},
		body: USER_LOC_body
	};
	
	let response = await fetch('http://localhost:3000/saveconfig', myOptions);
	
	console.log(response.headers.get('Content-Type'));
	
	let USER_LOC_text = await response.text();
	
	console.log(USER_LOC_text);

}

Ramirezkiv2
() автор топика
Ответ на: комментарий от anonymous

Решение о не использовании localstorage принималось исходя из того, что там использование СУБД и зависимость от связки домен+протокол+браузер. Посчитал это слишком навороченным и несерьёзным решением.

Ramirezkiv2
() автор топика
Ответ на: комментарий от Ramirezkiv2

Чего-чего? А сервер с нодой городить на клиенте - это не навороченное и серьезное решение?

использование СУБД

Которая уже есть в браузере.

зависимость от связки домен+протокол+браузер

Так тебе ещё и надо, чтоб один клиент к этим данным доступ из разных браузеров получал?

anonymous
()
Ответ на: комментарий от anonymous

Так тебе ещё и надо, чтоб один клиент к этим данным доступ из разных браузеров получал?

Нет конечно, просто получается, что это неприятная для меня особенность. Да забыл упомянуть, что в случае с использованием localstorage, нет понимания где сохраняемые данные хранятся на жёстком диске. В случае же использования серверной стороны для сохранения данных - данные будут хранится в том файле, который я непосредственно укажу явным образом. Его же можно будет потом взять и пересохранить в другое место.

Ramirezkiv2
() автор топика
Ответ на: комментарий от Ramirezkiv2

что в случае с использованием localstorage, нет понимания где сохраняемые данные хранятся на жёстком диске.

Буквально один запрос в Гугле или каком-нибудь дипсике. Так понимаю, есть принципиальная позиция «делать все через жопу» + нежелание узнавать новую информацию, которая легко доступна.

Я понимаю, что твое решение скорее всего не троллинг, и это печалит больше всего.

anonymous
()
Ответ на: комментарий от anonymous

А можно узнать почему решение сохранения текстовой инфы через серверную сторону трактуется вами как «делать всё через жопу», зато localstorage - то что доктор прописал?

Если бы новая информация была бы действительно легко и доступна, то я не задавал бы вопросов на форумах.

Это не моё решение, это решение создателей Nodejs, к ним есть какие-то претензии?

Ramirezkiv2
() автор топика
Ответ на: комментарий от Ramirezkiv2

почему решение сохранения текстовой инфы через серверную сторону трактуется вами

Потому что ты тащишь ненужную сущность, это надо на каждого клиента ставить ещё сервер? И все ради простой задачи.

Дело конечно ваше, и комментатора выше, но это на мой взгляд совсем плохая практика. Ну и отсутствие желания делать нормально, а не самым странным способом, меня тоже расстраивает. Потом этот костыль принесет за собой ещё костыли, потом все это станет непонятным монстром, а кто-то не дай бог будет делать так же.

anonymous
()
Ответ на: комментарий от anonymous

это надо на каждого клиента ставить ещё сервер? И все ради простой задачи.

Да, согласен, но каждый клиент - не простой юзер, а инженер-проектировщик. Задача простая, но очень важная, а как известно цель оправдывает средства.

Ну и отсутствие желания делать нормально, а не самым странным способом…

Ну вы выше сформулировали один критерий трактовки решения через Nodejs-сервер и касался он ненужной сущности. Получается, что всего лишь один недостаток низводит все мои усилия и низводит решение в ранг «самого странного», при этом являясь стандартным, потому что не костыли, а использование разработчика Nodejs.

Потом этот костыль принесет за собой ещё костыли, потом все это станет непонятным монстром

Ну вот если принесёт и станет, тогда и покритикуете ладно? А пока, что прога используется лично мной для проектирования, чему я несказанно рад. Задача по оптимизации решения меня пока не волнует - в рамках одного компа ресурсов используется очень немного.

ПС: вы прям так переживаете за применённое решение, как будто вы мой начальник, а я пишу прогу для вашей диссертации, не оптимальным способом))

Ramirezkiv2
() автор топика
Последнее исправление: Ramirezkiv2 (всего исправлений: 1)
Ответ на: комментарий от anonymous

Интересно вы сообщения читаете и трактуете как вздумается? Я кажется явным образом написал, что прога используется мной лично, а вы зачем-то уже успели на меня нагнать и раздуть из мухи слона )) Зачем вам это?

Ramirezkiv2
() автор топика
Ответ на: комментарий от Ramirezkiv2

каждый клиент - не простой юзер, а инженер-проектировщик.

Значит я не так понял. Плюс я не понял, если все данные крутятся локально, зачем там вообще нужна html страница в браузере.

Зачем вам это?

Ну, форум нужен для обмена опытом. Мне интересно было, почему ты не взял локалсторейдж, ты ответил что-то невнятное. Может быть ты потом вспомнишь этот тред, и сделаешь нормально.

Нет ведь никаких проблем бекапить профиль браузера целиком, или файл с localstorage.

anonymous
()
Ответ на: комментарий от anonymous

Плюс я не понял, если все данные крутятся локально, зачем там вообще нужна html страница в браузере.

Потому что именно html-страница мне предоставляет все инструменты для создания редактора проектирования так, как я не смог это сделать в средах типа Delphi/MS Visual Studio.

Мне интересно было, почему ты не взял локалсторейдж

Потому что быстрее разобрался с Nodejs и посчитал, что недостатки localstorage меня не устраивают.

ты ответил что-то невнятное

Я перечислил недостатки localstorage. Вы опять невнимательно всё поняли или включили уровень детского сада?

Может быть ты потом вспомнишь этот тред, и сделаешь нормально.

Уже сейчас сделано так, как меня вполне устраивает и то, что это не устраивает вас, то это не повод называть выбранное решение «странным» или «ненормальным», только потому, что там используется дополнительная сущность и всё, других аргументов у вас нет.

Нет ведь никаких проблем бекапить профиль браузера целиком, или файл с localstorage.

Может быть и не было, но дорога ложка к обеду, а ваш «ценный» совет несколько запоздал, поэтому сделано так, как вас нервирует. Будете продолжать спорить по уже давно решённой задаче?

Ramirezkiv2
() автор топика
Ответ на: комментарий от Ramirezkiv2

Твое решение это твое решение, ваши проблемы.

Я понять не могу, где ты увидел.

недостатки localstorage

// Думал ты новорег на лоре, а нет - 10 лет почти аккаунту. И такие вопросы.. данинг крюгером погоняет.

anonymous
()
Ответ на: комментарий от Ramirezkiv2

Будете продолжать спорить по уже давно решённой задаче?

Лично мне бы не хотелось, чтобы подобное решение висело в этом разделе как решенное, а то вдруг какой ещё человек поведется (один уже есть, в комментах выше).

Вот это «решение задачи» - это не решение. Это костыль уровня того форумчанина, который тут продавал свои услуги по 20р в час.

Вместо 3 строк кода на клиенте вот это все.

anonymous
()
Ответ на: комментарий от anonymous

Ну хорошо, у тебя винда и свой особый путь.

Но даже на встроенном повершелле, если уж очень хочется делать колхоз, можно поднять веб сервер и принимать-отдавать данные.

anonymous
()
Ответ на: комментарий от anonymous

А не, не угнали. Такое же отсутствие знаний, невдупления в задачу + много наглости. Удивительно, как человек за 10 лет совсем не смог в развитие.

И тогда были все идиоты, и теперь, поэтому мы получаем в этом треде печальный итог. 10 лет почти!!!!

Определение нагрузки на Web-приложение (комментарий)

anonymous
()
Ответ на: комментарий от anonymous

Прикольный тред там был, прочитал до конца, итог хорош Определение нагрузки на Web-приложение (комментарий)

Ты там ещё что-то про архитекторов говорил. Я правильно понимаю, что ты считаешь себя архитектором? В контексте этого треда и ОП звучит очень весело.

anonymous
()
Ответ на: комментарий от anonymous

Какой блестящий поиск информации и столько много внимания к моему аккуанту. Какая великолепная логика и непревзойдённый анализ нарытой информации и такой печальный итог! Чтож, вы вывели меня на чистую! Ещё есть ко мне претензии по делу?

Ramirezkiv2
() автор топика
Ответ на: комментарий от ya-betmen

Спросил и получил ответ в стиле «потому что потому». Теперь спрашиваю, а чем сохранение данных в файл с помощью Nodejs-сервера хуже, чем сохранение в сторадж браузера?

Ramirezkiv2
() автор топика