Javascript принудительно вызывает асинхронный обратный вызов сторонней функции, которая может выполнять синхронизацию или асинхронность - PullRequest
0 голосов
/ 20 декабря 2018

У меня проблемы с тем, чтобы понять, как работает следующая функция из этой онлайновой книги 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(..) (асинхронный или синхронный).Может ли кто-нибудь объяснить оба случая шагами, которые происходят между ними?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...