открытие файла-chooser не работает внутри вложенного setTimeout [дубликат]

Короткий ответ: вам нужно выполнить обратный вызов следующим образом:

function callback(response) {
    // Here you can do what ever you want with the response object.
    console.log(response);
}

$.ajax({
    url: "...",
    success: callback
});
30
задан Alex 24 April 2015 в 06:08
поделиться

3 ответа

Невозможно прямо сейчас открыть всплывающее окно файла из обратного вызова async ajax из-за рекомендованных w3c функций безопасности в браузерах.

В поведении активации элемента ввода файла он сначала проверяет, разрешено ли алгоритму отображать всплывающее окно, а затем отменяет последующие шаги, не делая ничего другого. из w3c.org

Алгоритму разрешено показывать всплывающее окно, если выполнено одно из следующих условий:

  1. Задача, в которой алгоритм работает в настоящее время обрабатывает поведение активации, которому было доверено событие клика. (доверенные события: события, которые генерируются пользовательским агентом, либо в результате взаимодействия с пользователем, либо как прямой результат изменений в DOM, доверяются пользовательский агент с привилегиями, которые не предоставляются событиям, генерируемым скриптом, методом DocumentEvent.createEvent("Event"), модифицированным с помощью метода Event.initEvent() или отправленным методом EventTarget.dispatchEvent(). Атрибут isTrusted доверенных событий имеет значение true, а недоверенные события имеют значение атрибута isTrusted false. В противном случае. http://www.w3.org/TR/2012/WD-DOM-Level-3-Events-20120614/#trusted-events .)
  2. Задача, в которой выполняется алгоритм, в настоящее время запускает прослушиватель событий для доверенного события, тип которого находится в следующем списке: change click dblclick mouseup reset submit
  3. Задача, в которой работает алгоритм, была поставлена ​​в очередь алгоритмом, которому было разрешено отображать всплывающее окно, а цепочка таких алгоритмов запускалась в пределах определенного пользователем периода времени.

w3c.org

В вашем коде событие клика не запускается пользователем, а запускается с помощью полного обратного вызова ajax. Здесь браузер заявляет, что этому событию нельзя доверять, чтобы открыть всплывающее окно. В некоторых браузерах вы можете видеть, что атрибут isTrusted установлен в true, если событие объявлено как доверенное. https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted

Примечание

Различные браузеры ловят разницу между активированным скриптом cick и реальным пользователем с использованием разных методов.

Что вы можете сделать в этом сценарии, для отключения кнопки ввода файла (или всей формы) и включения после завершения ajax. Таким образом, пользователь не будет нажимать кнопку загрузки до тех пор, пока запрос ajax не будет завершен. На данный момент нет другого способа сделать это за один клик, так как для открытия всплывающего окна есть ограничение по таймфрейму. Когда я проверил в хроме, таймфрейм равен 1000 мс. 1000 мс после действия пользователя, окно не открывается.

26
ответ дан tkay 23 August 2018 в 22:01
поделиться

Сам JQuery говорит, что триггер не будет работать для таких элементов, как загрузка файлов и привязка. (источник - https://learn.jquery.com/events/triggering-event-handlers/ )

Функция .trigger () не может использоваться для имитации например, нажатие на поле ввода файла или якорный тег. Это связано с тем, что обработчик событий не связан с системой событий jQuery, которая соответствует этим событиям.

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

  • document.createEvent
  • event.initMouseEvent
  • element.dispatchEvent

Пример кода + определение для вышеупомянутые функции можно найти на сайте разработчика Mozilla

https://developer.mozilla.org/samples/domref/dispatchEvent.html

Возможно , это поможет вам.

0
ответ дан Adersh M 23 August 2018 в 22:01
поделиться

У меня есть решение, которое работает сейчас. Это взлом, поэтому он может не работать в ближайшем будущем, поскольку он обходит функции безопасности, упомянутые выше Ткаем.

Я ввожу таймаут, ожидающий запроса ajax, чтобы вернуть данные, которые я хочу проверить, прежде чем запускать диалог браузера файлов.

customFileUploadButton.addEventListener('click', function(e) {

    var returnValueToCheck; //Value we want to check against

    //reference to vanilla JS ajax function that takes callback
    ajax(function(ajaxData) { 
        returnValueToCheck = ajaxData;
    });

    setTimeout(function() {
        if (returnValueToCheck !== undefined) { //dummy check for example
            file.click();
        } else {
           console.log("Criteria not fulfilled");
        }
    }, 1000);//timer should be larger than AJAX timeout
});

Честно говоря, я немного не уверен, почему именно эта работа за исключением явно проходящих определенных браузеров тестов, обычно запрещающих такое поведение. Поэтому я рассматриваю это как хак.

Моим примером является vanilla JS, но создать jQuery-версию должно быть легко. См. Этот JSFiddle для полного примера.

(Это мое первое участие в создании, поэтому, пожалуйста, прокомментируйте возможные ошибки и недочеты)

0
ответ дан Heenrik 23 August 2018 в 22:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: