Не удалось ли Node вернуть значение из вызова функции перед выполнением всех операций внутри самой функции?

У меня возникли проблемы с пониманием того, как Node работает относительно параллельной обработки и возвращает значения из вызовов функций.

FYI: Ниже приведена функция gulp ниже, как пример для этого вопроса.

Возможно ли, что функция может вернуть поток перед завершением операции Read a large file (большой файл был полностью прочитан из файловой системы и добавлен поток), или Node достаточно умный, чтобы завершить все заявления перед возвратом?

function moveFiles(){

    var gulp = require('gulp'),
        stream = require('merge-stream')();

    // Read a large file
    stream.add(gulp.src('src/large-file.txt')
        .pipe(gulp.dest('dest/'))
    );

    // Read a small file
    stream.add(gulp.src('src/small-file.txt')
        .pipe(gulp.dest('dest/'))
    );

    return (stream.isEmpty() ? null : stream);

}

Ответ 1

Возможно ли Node вернуть значение из вызова функции перед выполнением всех операций внутри самой функции?

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

Но сложная часть состоит в том, что она завершила выполнение функции, и это не означает, что она не может планировать, что еще что-то произойдет в будущем. Это будет усложняться через минуту, но сначала очень простой пример.

function x() {
    setTimeout(function () {
        console.log('x1'));
    }, 2000);
    console.log('x2');
    return;
    console.log('x3');
}

Здесь, когда вы вызываете x(), тогда будет назначена другая функция для запуска через 2 секунды, затем она будет печатать x2, а затем она вернется - в этот момент эта функция больше не сможет делать что-либо еще для этого вызова.

Это означает, что x3 никогда не будет напечатано, но x1 в конечном итоге будет напечатано - потому что это другая функция, которая будет вызываться, когда срабатывает тайм-аут. Анонимная функция будет вызвана не потому, что функция x() может что-то сделать после ее возвращения, а потому, что ей удалось запланировать таймаут до его возврата.

Теперь вместо того, чтобы просто планировать, что произойдет в будущем, функция может вернуть обещание, которое будет разрешено через некоторое время. Например:

function y() {
    console.log('y1');
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve('message from y()');
        }, 2000);
    });
    console.log('y2');
}

Теперь, когда вы запустите:

var promise = y();

произойдет следующее: y1 будет напечатано, новое обещание будет возвращено, а y2 никогда не будет напечатано, потому что в этот момент y() вернется и больше ничего не сможет сделать. Но ему удалось запланировать тайм-аут, который разрешит обещание через две секунды.

Вы можете наблюдать это:

promise.then(function (value) {
    console.log(value);
});

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

Поэтому я надеюсь, теперь ясно, почему это сложный вопрос. В некотором смысле функция не может ничего сделать после возвращения. Но он мог планировать некоторые другие функции как тайм-ауты, обработчики событий и т.д., Которые могут что-то сделать после возвращения функций. И если вещь, возвращаемая функцией, является обещанием, тогда вызывающий может легко наблюдать значение в будущем, когда оно будет готово.

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

Подробнее см. некоторые из этих ответов: