【问题标题】:How to execute callback function while resursive function is running in Javascript?当递归函数在Javascript中运行时如何执行回调函数?
【发布时间】:2020-06-25 05:36:19
【问题描述】:

递归函数运行时不能运行回调函数?

递归斐波那契函数和setInterval()的示例代码

'use strict';

function fibo(x) {
  if (x === 0) {
    console.info('fibo( ' + x + ' ) == 0');
    return 0;
  } else if (x === 1) {
    console.info('fibo( ' + x + ' ) == 1');
    return 1;
  }
  return fibo(x-2) + fibo(x-1);
};

fibo(10);

setInterval(() =>{console.info('hello')},10);

执行此代码,在 fibo(10) 完成工作后运行 setInterval。

如何在 fibo() 运行时显示 'hello' 日志? 递归函数运行时是否可以切入回调函数?

【问题讨论】:

  • setIntervalsetTimeout 调用在所有同步调用完成后运行。如果你运行很长的forwhile 循环,也会发生同样的情况

标签: javascript recursion callback stack


【解决方案1】:

如何在 fibo() 运行时显示 'hello' 日志?

由于fibo 是同步的,所以在正常情况下不能。 JavaScript 基于为作业队列服务的线程工作。当一个作业正在运行时,没有其他作业可以在该线程上运行(例如由setInterval 排队以调用您的回调的作业)。每个realm(松散地,全局环境)只有一个线程,所有主要环境(包括浏览器)只有一个主线程。您可以创建其他人,但他们有自己的环境。

你有几个选择:

  1. 使fibo 异步,每次调用它都会在另一个作业中安排下一个调用(例如通过setTimeout)。
  2. fibo 设为生成器函数,并为值重复调用它,将这些调用穿插在您的 setInterval 回调中。
  3. 使用工作线程。

由于您的 setInterval 代码和您的 fibo 代码不共享任何数据,因此使用工作线程是有意义的:

main.js:

'use strict';

function fibo(x) {
  if (x === 0) {
    console.info('fibo( ' + x + ' ) == 0');
    return 0;
  } else if (x === 1) {
    console.info('fibo( ' + x + ' ) == 1');
    return 1;
  }
  return fibo(x-2) + fibo(x-1);
};

new Worker("worker.js");
fibo(10);

worker.js:

setInterval(() =>{console.info('hello')},10);

如果他们共享数据,您可以使用shared memory,但要注意同步问题。

【讨论】:

  • @GrossMatt - 如果您要使 fibo 异步,您需要在某处跟踪状态(类似堆栈的结构)。请注意,它的运行速度也会慢很多。
  • 递归函数只是一个需要很长时间才能结束的函数的一个例子。如果我在 javascript 服务器上运行的 web 服务既有像实时 3d 渲染这样的繁重工作,也有像 CRUD 这样的轻量工作,我应该让繁重的工作异步,因为 JS 只能同时做一件事。是否有一个通用的解决方案来使大的while循环或递归函数异步?
  • @GrossMatt - 一般的解决方案是“将工作分解成块,一次做一个块”。但是在您描述的情况下,我会使用工作线程或子进程进行 3D 渲染。对于 Web 服务器(或任何服务器),您希望避免阻塞执行服务的线程。
  • 感谢您的回答!我认为 JS 比我想象的要复杂。用DOM做单页动画没那么难,但是node.JS服务端编程没那么简单......
猜你喜欢
  • 2021-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 1970-01-01
  • 1970-01-01
  • 2021-08-10
  • 1970-01-01
相关资源
最近更新 更多