Node pourrait-il renvoyer une valeur à partir d'un appel de fonction avant de terminer toutes les opérations dans la fonction elle-même?

J'ai du mal à comprendre comment fonctionne Node en ce qui concerne le traitement parallèle et le retour des valeurs des appels de fonctions.

FYI: la fonction gulp ci-dessous est simplement créée comme exemple pour cette question.

Est-il possible que la fonction puisse renvoyer le flux avant que l'instruction Read a large file ait fini son traitement (le fichier étendu a été entièrement lu à partir du système de fichiers et le flux a été ajouté) ou est Node assez intelligent pour remplir toutes les déclarations avant Revenir?

 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); } 

Node pourrait-il renvoyer une valeur à partir d'un appel de fonction avant de terminer toutes les opérations dans la fonction elle-même?

C'est une question délicate. La réponse est non, de sorte que le renvoi d'une valeur signifie que la fonction est terminée, elle est reprise de la pile et elle ne fera jamais rien à nouveau – sauf si elle est invoquée à un autre moment, bien sûr, mais cette invocation particulière est fini.

Mais la partie délicate est que c'est la fonction qui finit d'être exécutée et cela ne veut pas dire qu'il ne pourrait pas programmer autre chose à l'avenir. Il deviendra plus compliqué dans une minute, mais d'abord un exemple très simple.

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

Ici, lorsque vous appelez x() il programmera une autre fonction pour fonctionner après 2 secondes, puis il va imprimer x2 et ensuite il va revenir – auquel point cette fonction ne peut plus rien faire pour cette invocation.

Cela signifie que x3 ne sera jamais imprimé, mais x1 finira par être imprimé, car c'est une autre fonction qui sera appelée lors de l'extinction du délai d'attente. La fonction anonyme sera appelée non pas parce que la fonction x() peut tout faire après son retour, mais parce qu'elle a réussi à programmer le délai d'attente avant de revenir.

Maintenant, au lieu de simplement programmer des choses pour arriver à l'avenir, une fonction peut renvoyer une promesse qui sera résolu quelque temps plus tard. Par exemple:

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

Maintenant, lorsque vous exécutez:

 var promise = y(); 

Ce qui se passera, c'est que y1 sera imprimé, une nouvelle promesse sera retournée et y2 ne sera jamais imprimé car à ce moment-là, y() est revenu et ne peut rien faire d'autre chose. Mais il a réussi à planifier un délai qui résoudra la promesse après deux secondes.

Vous pouvez l'observer avec:

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

Donc, avec cet exemple, vous pouvez voir que la fonction y() elle-même est retournée et ne peut rien faire d'autre, une autre fonction (anonyme dans ce cas) peut être appelée à l'avenir et terminer le travail que la fonction y() a démarré.

J'espère maintenant qu'il est clair pourquoi c'est une question délicate. D'une certaine manière, une fonction ne peut rien faire après son retour. Mais il aurait pu programmer d'autres fonctions comme timeouts, gestionnaires d'événements, etc., qui peuvent faire quelque chose après le retour des fonctions. Et si la chose que la fonction retourne est une promesse alors l'appelant peut facilement observer la valeur dans le futur quand elle est prête.

Tous les exemples pourraient être simplifiés en utilisant les fonctions de la flèche, mais je voulais préciser que toutes sont des fonctions distinctes, certaines sont nommées, certaines sont anonymes.

Pour plus de détails, voir certaines de ces réponses:

  • Une explication détaillée sur la façon d'utiliser les rappels et les promesses
  • Explication sur la façon d'utiliser les promesses dans les gestionnaires de demandes complexes
  • Une explication de ce qu'est vraiment une promesse, à l'exemple des demandes AJAX
  • Une explication des rappels, des promesses et de l'accès aux données est retournée de manière asynchrone