Maison >interface Web >js tutoriel >Explication détaillée des fonctions de file d'attente JavaScript et de l'exécution asynchrone
Cet article présente principalement les informations pertinentes sur la fonction de file d'attente JavaScript et l'exécution asynchrone en détail. Il a une certaine valeur de référence. Les amis intéressés peuvent se référer à
Modifier Remarque : j'ai vu un article similaire. fonction de file d'attente lors de l'examen du code JavaScript d'autres personnes, mais je ne l'ai pas bien compris. Il s'avère que c'est pour garantir que les fonctions sont appelées dans l'ordre. Après avoir lu cet article, j'ai découvert qu'il pouvait également être utilisé pour une exécution asynchrone, etc.
Supposons que vous ayez plusieurs fonctions fn1, fn2 et fn3 qui doivent être appelées dans l'ordre. La manière la plus simple est bien sûr :
fn1(); fn2(); fn3();<.>
var stack = []; // 执行其他操作,定义fn1 stack.push(fn1); // 执行其他操作,定义fn2、fn3 stack.push(fn2, fn3); // 调用的时候 stack.forEach(function(fn) { fn() });
fonction anonyme directement. Testons-le :
var stack = []; function fn1() { console.log('第一个调用'); } stack.push(fn1); function fn2() { console.log('第二个调用'); } stack.push(fn2, function() { console.log('第三个调用') }); stack.forEach(function(fn) { fn() }); // 按顺序输出'第一个调用'、'第二个调用'、'第三个调用'
console.log(1); setTimeout(function() { console.log(2); }, 0); console.log(3);
var stack = []; function fn1() { console.log('第一个调用') }; stack.push(fn1); function fn2() { setTimeout(function fn2Timeout() { console.log('第二个调用'); }, 0); } stack.push(fn2, function() { console.log('第三个调用') }); stack.forEach(function(fn) { fn() }); // 输出'第一个调用'、'第三个调用'、'第二个调用'
function fn2() { setTimeout(function() { fn2Timeout(); fn3(); }, 0); }.
Nous prenons du recul et n'insistons pas pour attendre que fn2Timeout soit complètement exécuté avant d'exécuter fn3. Nous l'appelons plutôt sur la dernière ligne du corps de la fonction fn2Timeout :
function fn2() { setTimeout(function fn2Timeout() { console.log('第二个调用'); fn3(); // 注{1} }, 0); }
Cela semble mieux, mais lorsque fn2 a été défini, il n'y avait pas encore de fn3. D'où vient fn3 ?
Il y a un autre problème. Puisque fn3 doit être appelé dans fn2, nous ne pouvons pas appeler fn3 via stack.forEach, sinon fn3 sera appelé deux fois.
Nous ne pouvons pas écrire fn3 dans fn2. Au lieu de cela, il nous suffit de trouver la fonction suivante de fn2 dans la pile à la fin de fn2Timeout, puis d'appeler :
function fn2() { setTimeout(function fn2Timeout() { console.log('第二个调用'); next(); }, 0); }
Cette fonction suivante est chargée de trouver la fonction suivante dans la pile et de l'exécuter. Implémentons ensuite maintenant :
var index = 0; function next() { var fn = stack[index]; index = index + 1; // 其实也可以用shift 把fn 拿出来 if (typeof fn === 'function') fn(); }
next utilise stack[index] pour obtenir les fonctions dans la pile Calling. la prochaine fois augmentera l'indice de 1, atteignant ainsi l'objectif de supprimer la fonction suivante.
var stack = []; // 定义index 和next function fn1() { console.log('第一个调用'); next(); // stack 中每一个函数都必须调用`next` }; stack.push(fn1); function fn2() { setTimeout(function fn2Timeout() { console.log('第二个调用'); next(); // 调用`next` }, 0); } stack.push(fn2, function() { console.log('第三个调用'); next(); // 最后一个可以不调用,调用也没用。 }); next(); // 调用next,最终按顺序输出'第一个调用'、'第二个调用'、'第三个调用'。
Maintenant, la ligne stack.forEach a été supprimée, nous appelons-le nous-mêmes Une fois ensuite, next trouvera la première fonction fn1 dans la pile à exécuter, appellera next dans fn1 pour trouver la fonction suivante fn2 et l'exécutera, puis appellera next dans fn2, et ainsi de suite.
Après avoir compris cette implémentation de la file d'attente des fonctions, vous devriez être capable de résoudre la question d'entretien suivante :
// 实现一个LazyMan,可以按照以下方式调用: LazyMan(“Hank”) /* 输出: Hi! This is Hank! */ LazyMan(“Hank”).sleep(10).eat(“dinner”)输出 /* 输出: Hi! This is Hank! // 等待10秒.. Wake up after 10 Eat dinner~ */ LazyMan(“Hank”).eat(“dinner”).eat(“supper”) /* 输出: Hi This is Hank! Eat dinner~ Eat supper~ */ LazyMan(“Hank”).sleepFirst(5).eat(“supper”) /* 等待5秒,输出 Wake up after 5 Hi This is Hank! Eat supper */ // 以此类推。
C'est ainsi que le célèbre connectframework implémente la file d'attente middleware. Si vous êtes intéressé, vous pouvez jeter un oeil à son code source ou à cette explication "Qu'est-ce que le middleware de connexion".
Si vous faites attention, vous verrez peut-être que ce next ne peut être placé qu'à la fin de la fonction pour le moment. S'il est placé au milieu, le problème d'origine se produira toujours :
function fn() { console.log(1); next(); console.log(2); // next()如果调用了异步函数,console.log(2)就会先执行 }
Grâce à différentes implémentations, redux et koa peuvent se placer ensuite au milieu de la fonction. fonction suivante, il peut ensuite être rétabli pour exécuter ensuite le code ci-dessous. Écrivez à nouveau quand vous aurez le temps.
Ce qui précède représente l'intégralité du contenu de cet article. J'espère qu'il sera utile à l'étude de chacun. J'espère également que tout le monde soutiendra Script House.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!