2017-01-23 3 views
1

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

function synchronous(){ 
    var notYet = true; 

    setTimeout(function(){ 
     notYet = false; 
    }, 1000); 

    while(notYet) 
     ; 

    return "Done synchronously!"; 
} 

console.log(synchronous()); 

Здесь функции synchronous стойла с помощью while петли неда обратного вызова асинхронной функции (здесь setTimeout) получить казнен. Но обратный вызов никогда не вызывается (проверяется с использованием alert внутри обратного вызова), поэтому notYet останется true, и цикл функций будет продолжаться вечно. Итак, почему callback не вызван после 1000 мс?

ПРИМЕЧАНИЕ: Мне все равно, как сделать асинхронную функцию синхронной. Мой вопрос в том, почему вызов не вызван?

+1

браузер javascript - это однопоточный язык – Igor

ответ

6

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

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

NodeJS также запускает ваш код в одном потоке и делает то же самое. (Не во всех средах, но я не знаю никого с setTimeout, которые не планируют обратный вызов таймера в том же потоке, который его запросил.)

+0

Я это разбираюсь. Затем я заменил цикл while while функцией рекурсии, чтобы дать возможность выполнить обратный вызов. Но не получилось. Я отправлю код, если вы хотите взглянуть. –

+1

@ibrahimmahrir: Рекурсивная функция тоже не уступает, она просто продолжает рекурсию. Подумайте об этом: если 'foo' вызывает' bar', вы не хотите, чтобы доход был посередине (если вы пишете однопоточный код, что намного проще, чем писать многопоточный код, следовательно, эта модель используется в браузерах). 'foo' callling' foo' ничем не отличается. Единственный способ вернуть его - это «упасть» с конца кода. –

+1

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

Смежные вопросы