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

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

К вашему сведению: приведенная ниже функция глотка просто создана в качестве примера для этого вопроса.

Возможно ли, что функция может вернуть поток до 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() Функция инициирована.

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

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

Для получения более подробной информации см. Некоторые из этих ответов:

Другие вопросы по тегам