Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 19.11.2018, 16:33
Аспирант
Отправить личное сообщение для Svorg Посмотреть профиль Найти все сообщения от Svorg
 
Регистрация: 16.11.2018
Сообщений: 38

Улучшаем работу с FormData
Случайно обнаружил, что при использовании FormData в браузере Chrome эти объекты почему-то не нормально отображаются в консоли.
Например, делаем так:
let formData = new FormData();
formData.append('test', 'ololo');
formData.append('ID', '666');
console.info('formData == ' + formData);
console.info('formData ~>', formData);
console.info('formData << ' + formData.toSource());
А в выводе консоли получаем такое безобразие:
Цитата:
formData == [object FormData]
formData ~> FormData {}
Uncaught TypeError: formData.toSource is not a function
Хотя на самом-то деле сами объекты нормальные/корректные и содержат все наши добавленные данные.
И тогда я стал добавлять такой финт:
formData.toString = function() {
  let r = {};
  for (let e of this.entries()) {
    if (r[e[0]]) {
      r[e[0]].push(e[1]);
    } else {
      r[e[0]] = [e[1]];
    };
  };
  return JSON.stringify(r, null, '\t');
};
Становится явно лучше. Но однажды я столкнулся ещё с тем, что передаю FormData через POST запрос XMLHttpRequest, а оно берёт и не работает.
Сперва даже растерялся - всё же верно, фрагмент простейший, ошибок не может быть, просто негде. Но вскоре заметил, что вместо ожидаемого "test=ololo&ID=666" передаётся какая-то полная чушь.
Поэтому я сделал ещё такую заплатку:
formData.toSource = function() {
  let r = '';
  for (let e of this.entries()) {
    if (r.length > 0)
      r += '&';
    r += e[0] + '=' + encodeURIComponent(e[1]);
  };
  return r;
};
Теперь, если что, я могу передавать в send() не сам formData, а например formData.toSource(). Вывод консоли теперь получается такой:
Цитата:
formData == { "test": [ "ololo" ], "ID": [ "666" ] }
formData ~> FormData {}
formData << test=ololo&ID=666

А однажды у меня появилась необходимость делать ряд асинхронных запросов, с похожими FormData (отличались парой значений).
Не знаю что на меня нашло, но я объявил единый "шаблон" и стал тупо передавать его в функции (а те меняли/добавляли параметры и отправляли).
Разумеется огрёб кучу неполадок. Надо ж было шаблон клонировать, а не его же самого передавать!:
formData.clone = function() {
  let clone = new FormData();
  for (let e of this.entries()) {
    clone.append(e[0], e[1]);
  };
  return clone;
};
И разумеется это всё можно засунуть в "prototype":
FormData.prototype.toString = function() {
  let r = {};
  for (let e of this.entries()) {
    if (r[e[0]]) {
      r[e[0]].push(e[1]);
    } else {
      r[e[0]] = [e[1]];
    };
  };
  return JSON.stringify(r, null, '\t');
};
FormData.prototype.toSource = function() {
  let r = '';
  for (let e of this.entries()) {
    if (r.length > 0)
      r += '&';
    r += e[0] + '=' + encodeURIComponent(e[1]);
  };
  return r;
};
FormData.prototype.clone = function() {
  let clone = new FormData();
  for (let e of this.entries()) {
    clone.append(e[0], e[1]);
  };
  return clone;
};
//TODO: Далее думаю было бы неплохо ещё сделать чтоб параметры и значения можно было хранить и подгружать в виде объектов, типа:
let defaultParams = {
  'test': 'ololo',
  'ID': '666'
};
let formData = new FormData();
formData.addParams(defaultParams);
Ответить с цитированием
  #2 (permalink)  
Старый 19.11.2018, 19:11
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Сообщение от Svorg
эти объекты почему-то не нормально отображаются в консоли
Стоит учитывать, что FormData — контейнерный тип, который условно можно представить так — FormData<String, String | Blob>. Это интерфейс для работы с данными формы, было бы странно, если бы он тянул за собой всевозможные парсеры для отображения/проигрывания файлов в консоли. Вы можете взглянуть на то, что перечисляет итератор для представителей класса FormData
console.log("form data", ...formData);

Сообщение от Svorg
formData.toString... Становится явно лучше... сделал ещё такую заплатку formData.toSource
Взяли и неожиданно закрыли работу с файлами.

Сообщение от Svorg
И разумеется это всё можно засунуть в "prototype"
Это (toString и toSource) совершенно бессмысленные костыли, которые к тому же не правильно работают.


Сообщение от Svorg
Далее думаю было бы неплохо ещё сделать чтоб параметры и значения можно было хранить и подгружать в виде объектов
Вы выбрали не тот инструмент, как я понял, если вам не нужна работа с файлами, то используйте URLSearchParams

var defaultParams = {
	test: "ololo",
	ID: "666"
};
var params = new URLSearchParams(defaultParams);
alert(params.toString());


var defaultParams = "test=ololo&ID=666";
var params = new URLSearchParams(defaultParams);
alert(params.toString());


клонирование
var params = new URLSearchParams({
	test: "ololo",
	ID: "666"
});

var params2 = new URLSearchParams(params);
params2.set("ID", "777");

alert(params2.toString());
Ответить с цитированием
  #3 (permalink)  
Старый 20.11.2018, 09:56
Аспирант
Отправить личное сообщение для Svorg Посмотреть профиль Найти все сообщения от Svorg
 
Регистрация: 16.11.2018
Сообщений: 38

У меня FormData и XMLHttpRequest. FormData не отображается через console.log(). Никак. Пустота.
Кладу туда append('ID', '666') и ещё десяток значений - через console.log() всё равно пустота.
На форумах куча людей мучаются, потому что думают мол append() не работает, а он как раз работает.
Сообщение от Malleys
Взяли и неожиданно закрыли работу с файлами.
Ничего я не закрывал. Вывода вообще никакого не было, теперь есть. Файлы отобразятся как "" - а раньше вообще не было видно их наличия.
Сообщение от Malleys
бессмысленные костыли, которые к тому же не правильно работают.
Работают правильно. Смысл я объяснил вроде.
Ответить с цитированием
  #4 (permalink)  
Старый 20.11.2018, 14:37
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Сообщение от Svorg
через console.log() всё равно пустота
(async () => {
	const image = await fetch("https://placeimg.com/64/48/any", {
		mode: "no-cors"
	}).then(response => response.blob());

	const formData = new FormData();
	formData.append("id", "666");
	formData.append("image", image);

	console.log(formData);
	console.log(...formData);
	console.table([...formData]);

	return formData;
})();


Если что, то оно так выглядит — не пусто!

Последний раз редактировалось Malleys, 20.11.2018 в 14:49.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Массив файлов в FormData AlexProf AJAX и COMET 2 30.08.2018 14:27
Не работают некоторые методы объекта FormData avalan4e AJAX и COMET 4 04.08.2016 05:34
Ручное формирование FormData object Armatus AJAX и COMET 2 23.12.2015 15:59
Метод delete для formData bartonom jQuery 8 06.04.2015 20:39
formData ajax form upload imedia Элементы интерфейса 1 27.08.2014 20:17