У меня проблемы с тем, чтобы понять, как работает следующая функция из этой онлайновой книги javascript (You-Dont-Know-JS) ?Как эта функция включает асинхронное поведение при передаче сторонней функции (описанной в следующем фрагменте), которая может выполнять или не выполнять асинхронную работу?
function asyncify(fn) {
var orig_fn = fn,
intv = setTimeout( function(){
intv = null;
if (fn) fn();
}, 0 )
;
fn = null;
return function() {
// firing too quickly, before `intv` timer has fired to
// indicate async turn has passed?
if (intv) {
fn = orig_fn.bind.apply(
orig_fn,
// add the wrapper's `this` to the `bind(..)`
// call parameters, as well as currying any
// passed in parameters
[this].concat( [].slice.call( arguments ) )
);
}
// already async
else {
// invoke original function
orig_fn.apply( this, arguments );
}
};
}
В приведенной мной ссылке также приведен следующий пример кода о том, как выполнить asyncify(..)
:
function result(data) {
console.log( a );
}
var a = 0;
ajax( "..pre-cached-url..", asyncify( result ) );
a++;
Здесь ajax(..)
- это функция стороннего производителя, которая может выполнять асинхронную илисинхронизации.Для обеспечения асинхронного обратного вызова result(..)
автор вводит asyncify(..)
в качестве примера.Это приведет к тому, что вывод консоли всегда будет 1
(асинхронный).
Насколько я понимаю, функция fist определяет две переменные orig_fn
для хранения исходного дескриптора функции, в данном случае result()
,И intv
- это идентификатор таймера, возвращаемый из setTimeout
.
var orig_fn = fn,
intv = setTimeout( function(){
intv = null;
if (fn) fn();
}, 0 )
;
setTimeout(..,0)
означает что именно?Для немедленного выполнения при следующем запуске цикла событий?
Почему мы выполняем fn()
в функции обратного вызова setTimeout
и оператор else в функции возврата?Разве функция не вызывается дважды таким образом, когда ajax
работает асинхронно?Сначала при срабатывании таймера, который вызывает fn()
и снова при вызове orig_fn.apply(this, arguments)
?
Почему asyncify возвращает функцию, но также вызывает функцию fn
, переданную ей?
Что означает следующее в операторе if и даже fn
вызывается, если ajax
синхронно?
fn = orig_fn.bind.apply(
orig_fn,
// add the wrapper's `this` to the `bind(..)`
// call parameters, as well as currying any
// passed in parameters
[this].concat( [].slice.call( arguments ) )
);
- Почемупараметр
fn
установлен на исходную функцию?Для меня переменная fn
даже не используется после возврата?Или это ссылка на result()
, которая теперь изменяется путем добавления this
оболочки и аргументов?Если да, то зачем нужна this
оболочки?
Я думаю, моя главная проблема в понимании этой функции - как работает этот код в зависимости от того, как работает ajax(..)
(асинхронный или синхронный).Может ли кто-нибудь объяснить оба случая шагами, которые происходят между ними?