Использование thunk для выделения времени из асинхронного кода

У Кайла Симпсона потрясающий класс по множеству мнений.

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

Функция во всей красе:

    function getFile(file) {
    var text, fn;

    fakeAjax(file, function(response){
        if (fn) fn(response);
        else text = response;
    });

    return function(cb) {
        if (text) cb(text);
        else fn = cb;
    }
 }

Мы можем назвать это так:

Мне трудно понять функцию getFile:

  1. где определяется cb? как это называется, то есть cb(text) если это нигде не определено?
  2. когда мы вызываем getFile, как response получить значение вообще?

1 ответ

getFile возвращает анонимную функцию:

return function(cb) {
    if (text) cb(text);
    else fn = cb;
}

так var th1 = getFile("file") заканчивает тем, что присваивает эту анонимную функцию значению th1, так th1 теперь можно вызывать с аргументом - который становится cb, Поэтому, когда позже мы позвоним th1 с:

th1(function(text1) {
...

мы передаем вторую анонимную функцию (с аргументом text1), которая назначается cb (сокращение для "обратного вызова").

Причина, по которой он работает, заключается в том, что когда AJAX завершен, он выполняет одно из двух:

  • если fn определяется, звонки fn с ответом
  • если нет, то хранит ответ

И наоборот, когда вызывается возвращенная анонимная функция, она выполняет одно из двух:

  • если text определяется (т. е. результат уже получен), затем он вызывает обратный вызов с ответом
  • если нет, он назначает обратный вызов (cb) чтобы fn

Таким образом, в зависимости от того, что произойдет первым - ajax complete или thunk вызывается, состояние сохраняется, а затем, в зависимости от того, что происходит вторым, выполняется результат.

Таким образом, 'thunks' могут быть объединены в цепочку, чтобы гарантировать, что в то время как функции ajax происходят параллельно, методы вывода вызываются только в той последовательности, в которой fn значения назначены.

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

function getFile(file) {
    var _response, _callback;

    fakeAjax(file, function(response){
        if (_callback) _callback(response);
        else _response = response;
    });

    var onComplete = function(callback) {
        if (_response) callback(_response);
        else _callback = callback;
    }

    return onComplete;
}

затем:

var onFile1Complete = getFile("file1");
var onFile2Complete = getFile("file2");
var onFile3Complete = getFile("file3");

var file3Completed = function(file3Response) {
    output("file3Response");
    output("Complete!");
}

var file2Completed = function(file2Response) {
    output(file2Response);
    onfile3Complete(file3Completed)
}

var file1Completed = function(file1Response) {
    output(file1Response);
    onFile2Complete(file2Completed);
}

onFile1Complete(file1Completed);
Другие вопросы по тегам