Конечно, есть много таких подходов, как синхронный запрос, обещание, но из моего опыта я думаю, что вы должны использовать подход обратного вызова. Естественно, что асинхронное поведение Javascript. Итак, ваш фрагмент кода можно переписать немного иначе:
function foo() {
var result;
$.ajax({
url: '...',
success: function(response) {
myCallback(response);
}
});
return result;
}
function myCallback(response) {
// Does something.
}
Банкротство и захват событий - два способа распространения события в API DOM HTML, когда событие происходит в элементе внутри другого элемента, и оба элемента зарегистрировали дескриптор для этого события. Режим распространения событий определяет в , который упорядочивает элементы, получающие событие .
При барботировании событие сначала захватывается и обрабатывается самым внутренним элементом, а затем распространяется на внешние элементы.
С захватом событие сначала захватывается самым внешним элементом и распространяется на внутренние элементы.
Захват также называется «trickling», что помогает запомнить порядок распространения:
trickle down, bubble up
blockquote>. В прежние времена Netscape отстаивал захват событий, в то время как Microsoft продвигала пузыри событий. Оба являются частью стандарта W3C Events Object Model Model (2000).
IE & lt; 9 использует только событие bubbling события , тогда как IE9 + и все основные браузеры поддерживают оба. С другой стороны, производительность барботажа событий может быть несколько ниже для сложных DOM.
Мы можем использовать
addEventListener(type, listener, useCapture)
для регистрации обработчиков событий в обоих вариантах барботажа (по умолчанию) или режим захвата.Пример
<div> <ul> <li></li> </ul> </div>
В вышеприведенной структуре предположим, что событие click произошло в элементе
li
.При захвате модели событие будет обработано сначала
div
(сначала будут запускаться обработчики событий вdiv
), затем вul
, а затем на последнем в целевом элементli
.В модели барботирования произойдет обратное: событие будет обрабатываться в первую очередь
li
, затемul
и, наконец,div
Элемент.Для получения дополнительной информации см.
- Порядок событий на QuirksMode
- addEventListener на MDN
- События Расширенные на QuirksMode
В приведенном ниже примере, если вы нажмете на любой из выделенных элементов, вы увидите, что сначала происходит фаза захвата потока распространения события, затем фаза барботирования.
var logElement = document.getElementById('log'); function log(msg) { logElement.innerHTML += ('<p>' + msg + '</p>'); } function capture() { log('capture: ' + this.firstChild.nodeValue.trim()); } function bubble() { log('bubble: ' + this.firstChild.nodeValue.trim()); } var divs = document.getElementsByTagName('div'); for (var i = 0; i < divs.length; i++) { divs[i].addEventListener('click', capture, true); divs[i].addEventListener('click', bubble, false); }
p { line-height: 0; } div { display:inline-block; padding: 5px; background: #fff; border: 1px solid #aaa; cursor: pointer; } div:hover { border: 1px solid #faa; background: #fdd; }
<div>1 <div>2 <div>3 <div>4 <div>5</div> </div> </div> </div> </div> <section id="log"></section>
Также существует свойство Event.eventPhase
, которое может сказать вам, находится ли событие в целевой точке или происходит откуда-то еще.
Обратите внимание, что совместимость браузера еще не определена. Я тестировал его на Chrome (66.0.3359.181) и Firefox (59.0.3), и он поддерживается там.
Развернув на уже отличный фрагмент из принятого ответа , это результат с использованием свойства eventPhase
var logElement = document.getElementById('log');
function log(msg) {
if (logElement.innerHTML == "<p>No logs</p>")
logElement.innerHTML = "";
logElement.innerHTML += ('<p>' + msg + '</p>');
}
function humanizeEvent(eventPhase){
switch(eventPhase){
case 1: //Event.CAPTURING_PHASE
return "Event is being propagated through the target's ancestor objects";
case 2: //Event.AT_TARGET
return "The event has arrived at the event's target";
case 3: //Event.BUBBLING_PHASE
return "The event is propagating back up through the target's ancestors in reverse order";
}
}
function capture(e) {
log('capture: ' + this.firstChild.nodeValue.trim() + "; " +
humanizeEvent(e.eventPhase));
}
function bubble(e) {
log('bubble: ' + this.firstChild.nodeValue.trim() + "; " +
humanizeEvent(e.eventPhase));
}
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
divs[i].addEventListener('click', capture, true);
divs[i].addEventListener('click', bubble, false);
}
p {
line-height: 0;
}
div {
display:inline-block;
padding: 5px;
background: #fff;
border: 1px solid #aaa;
cursor: pointer;
}
div:hover {
border: 1px solid #faa;
background: #fdd;
}
<div>1
<div>2
<div>3
<div>4
<div>5</div>
</div>
</div>
</div>
</div>
<button onclick="document.getElementById('log').innerHTML = '<p>No logs</p>';">Clear logs</button>
<section id="log"></section>
Если есть два элемента: элемент 1 и элемент 2. Элемент 2 находится внутри элемента 1, и мы присоединяем обработчик событий, в котором оба элемента позволяют говорить onClick. Теперь, когда мы нажимаем на элемент 2, будет выполняться eventHandler для обоих элементов. Теперь здесь возникает вопрос, в каком порядке будет выполняться событие. Если событие, связанное с элементом 1, выполняется первым, оно называется захватом события, и если событие, связанное с элементом 2, выполняется первым, это называется барботированием событий. Согласно W3C событие начнется на этапе захвата до тех пор, пока оно не достигнет цели, возвращается к элементу, а затем начинает пузыриться
Состояние захвата и пузырения известно с помощью параметра useCapture метода addEventListener
eventTarget.addEventListener (type, listener, [, useCapture]);
blockquote>По умолчанию useCapture является ложным. Это означает, что он находится в фазе барботирования.
var div1 = document.querySelector("#div1"); var div2 = document.querySelector("#div2"); div1.addEventListener("click", function (event) { alert("you clicked on div 1"); }, true); div2.addEventListener("click", function (event) { alert("you clicked on div 2"); }, false);
#div1{ background-color:red; padding: 24px; } #div2{ background-color:green; }
<div id="div1"> div 1 <div id="div2"> div 2 </div> </div>
Попробуйте изменить true и false.
Описание:
quirksmode.org имеет хорошее описание этого. В двух словах (скопировано из quirksmode):
Запись события
Когда вы используете захват события
| | ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 \ / | | | ------------------------- | | Event CAPTURING | -----------------------------------
, обработчик события element1 срабатывает первым , обработчик события element2 срабатывает последним.
Событие bubbling
Когда вы используете барботирование событий
/ \ ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 | | | | | ------------------------- | | Event BUBBLING | -----------------------------------
, сначала запускается обработчик события element2, событие обработчик элемента1 срабатывает последним.
blockquote>
Что использовать?
Это зависит от того, что вы хотите сделать. Нет лучшего. Разница заключается в порядке выполнения обработчиков событий. В большинстве случаев будет нормально запускать обработчики событий на фазе bubbling , но также может потребоваться их запуск раньше.
Я нашел это учебник на javascript.info , чтобы быть очень ясным в объяснении этой темы. И его 3-балльное резюме в конце действительно разговаривает с критическими моментами. Я цитирую его здесь:
blockquote>
- События сначала захватываются до самой глубокой цели, а затем пузырятся. В IE & lt; 9 они только пузырьки.
- Все обработчики работают на стадии барботирования, кроме addEventListener с последним аргументом true, что является единственным способом поймать событие на этапе захвата.
- Bubbling / capture можно остановить event.cancelBubble = true (IE) или event.stopPropagation () для других браузеров.