TLDR: вы не можете, посмотрите основание вопроса для альтернативного решения (то есть, с тем, с которым я скомпрометировал).

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

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

Нажмите => ждать тайм-аут / обратного вызова => продолжить с обычного события.

ИЛИ

Нажмите => начать вызов и тайм-аут, отменить функцию обратного вызова / тайм-аута по умолчанию для продолжения / возобновить процесс нажатия

Я надеюсь, что все имеет смысл, заранее спасибо.

РЕДАКТИРОВАТЬ: вызов сервера не нужно завершать 100% времени.

РЕДАКТИРОВАТЬ: Я хочу продолжить исходную «функцию» события щелчка, а не заменять или редактировать переменную window.location, поскольку навигация не гарантируется, например, при нажатии на среднюю кнопку мыши.

РЕДАКТИРОВАТЬ: вот базовая структура кода (это действительно сложно):

item.onclick = function(){

var callback = function(){
    // continue as if nothing happened
    // including non-navigational clicks (e.g. middle-click)
};

// Send call with callback
sendCall(callback);

// if no callback not triggered in 250ms then continue anyway
setTimeout(callback, 250);

return false; // or not if there's a way to delay
}

РЕДАКТИРОВАТЬ . Похоже, что здесь нет полезного решения, поэтому я разместил код, который использовал в ответе.

0
Gianthra 18 Дек 2015 в 19:42

3 ответа

Лучший ответ

Вы можете запретить действие клика по умолчанию, чтобы ссылка не сработала при клике. Затем вы отправляете свой ajax-вызов, и когда он завершается, ваш код меняется на саму новую страницу.

Предполагая, что у вас уже есть обработчик кликов для ссылки, в которой вы делаете вызов ajax:

function myClickHandler(e) {
    e.preventDefault();
    var self = this;
    sendAjax(..., function() {
        // ajax call done here
        // do the page navigation
        window.location = self.href;
    })
}

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


Ответ на ваше изменение:

В Javascript нет метода, который блокировал бы выполнение Javascript в течение максимум 250 мс при обработке асинхронного вызова ajax, а затем продолжал нормальное выполнение. Таким образом, контур в вашем коде не представляется возможным напрямую, как вы это показали.

Обычный шаблон проектирования в Javascript состоит в том, чтобы предотвратить действие по умолчанию, настроить асинхронное действие (вызов ajax и таймер в вашем случае), а затем, когда это асинхронное событие завершится или истечет время ожидания, вы вручную запускаете действие по умолчанию. Но вы должны знать, как вызвать действие по умолчанию самостоятельно, чтобы сделать это (что и было показано в моем предложении кода выше).

Единственный обходной путь, о котором я могу подумать, это то, что вы можете отправить синхронный вызов Ajax (обычно это считается плохой практикой) с тайм-аутом, установленным для самого вызова ajax. Это приостановит выполнение вашего Javascript и все другие взаимодействия со страницей, пока вызов ajax не завершится или не истечет время ожидания. Вам нужно довольно тщательно протестировать это, чтобы увидеть, дает ли оно желаемое взаимодействие во многих браузерах, потому что это, конечно, не стандартная вещь, которая используется регулярно. Я лично не рекомендовал бы это (синхронный ajax - просто зло, поскольку это блокирует браузер).

С более полным пониманием того, какую проблему вы действительно пытаетесь решить, я бы искал лучшее решение. До сих пор вы описывали только свою попытку решения, а не реальную проблему, которую пытаетесь решить. Это известно как проблема XY и резко ограничивает то, как мы можем вам помочь.

3
Community 20 Мар 2017 в 10:29

Вот код, который я в итоге использовал, он проверяет, что щелчок левой кнопкой мыши или касание:

element.onclick = function(event){
    if(event.button == 0){
        var callback = function(){
            window.location = destinationUrl;
        };
        sendCall(callback);
        setTimeout(callback, 250);
        return false; // halt normal click propagation
    } else {
        sendCall();
    }
};
0
Gianthra 21 Дек 2015 в 09:11

Если вы хотите что-то сделать после успешного ajax, то, как упомянул пользователь до меня, вы можете использовать функцию успеха ajax для запуска желаемого поведения вместе с «mousedown» / «touchstart», чтобы сэкономить несколько мс вместо «щелчка».

jQuery('body').on('click','yourlink',function(e){
    e.preventDefaul;
    $.ajax({
        url: 'url here',
        type: 'POST',
        success: function() {
        //go to desired url
            window.location.replace = 'the url to navigate to';
        },
        error : function(){
         //ajax error handling code here
        }
     });
});

Не совсем понял, что вы имеете в виду под «я не могу использовать трюк window.location», но надеюсь, что это поможет.

Ура

1
Yuliyan Yordanov 18 Дек 2015 в 17:06