使用setTimeout

时间:2017-12-27 15:44:27

标签: javascript memory-leaks garbage-collection settimeout polling

我想知道是否有人可以帮我解决这个问题......

我们的客户端有一个Legacy API,用于检索用户的消息,他们希望我们为它实现一个轮询机制,根据特定的时间间隔更新页面中的信息。期。 他们希望有一个可靠的轮询策略(正如您可能已经知道的那样)我使用setTimeout将其关闭。

TL; DR :有没有人知道如何推出一个不会泄漏内存的高效轮询工具?

我试图启动一个实用程序,允许我将某些操作添加到"轮询列表"并运行"民意调查"就在那里。

例如,我有一个"动作列表"类似于:

const actions = new Map();

actions.set('1', ('1', {
    action: () => {
        console.log('action being executed...');
        return 'a value';
    },
    onFinished: (...param) => { console.log(param); },
    name: 'name of the action',
    id: '1'
}));

我使用Map来提供api方便性和查找性能,并且我在其中添加了一个假动作(可能不需要某些参数,但他们会在那里进行测试)。

关于轮询,我创建了一个延迟fn来处理作为Promise的超时(仅为了可读性。它不应该影响调用堆栈的使用):

function delay(timeout) {
    return new Promise(function delay(resolve) {
        setTimeout(resolve, timeout);
    });
}

我提出的民意调查结果如下:

async function do_stuff(id, interval) {
    const action = actions.get(id);

    // breakout condition
    if (action.status === 'stop') {
        return;
    }
    console.log('processing...');

    const response = await action.action();

    console.log('executing action onFinished...');
    action.onFinished(action.name, response);

    delay(interval).then(function callAgain() {
        do_stuff(id, interval);
    });
}

我在这里使用了async / await,因为我的action.action()主要是异步操作,我在延迟后使用.then,因为我想使用浏览器的EventTable处理我的解析函数而不是浏览器的堆栈。另外,我使用命名函数进行调试。

要运行轮询功能,我只需:

const actionId = '1';
const interval = 1000;
do_stuff(actionId, interval);

为了停止对该特定动作的调查,我运行:

actions.get(actionId).status = 'stop'; // not fancy but effective

到目前为止这么好......不是!这肯定有很多问题,但是最让我困扰的是JS Heap的使用。 我使用Chrome DevTools(Chrome版本64)的Performance Tab运行了几个测试,这就是我得到的:

使用10毫秒的间隔   - 1000ms:开始投票   - 10000ms:轮询停止   - 13000ms:运行手动GC

10 milliseconds heap

使用1秒的间隔

  • 1000ms:开始投票
  • 10000ms:轮询已停止
  • 13000ms:运行手动GC

1 second heap

有谁知道为什么这样做?为什么GC在减少间隔时会更频繁地运行?是内存泄漏还是堆栈问题?有什么工具可以用来继续调查这个问题吗?

提前致谢!

我读过的东西:

PS:我已经把这个片段放在这里以防万一有人想试一试。



const actions = new Map();
actions.set('1', ('1', {
	action: () => {
		console.log('action being executed...');

		return 'a value';
	},
	onFinished: (...param) => { console.log(param); },
	name: 'name of the action',
	id: '1'
}));

function delay(timeout) {
	return new Promise(function delay(resolve) {
		setTimeout(resolve, timeout);
	});
}

async function do_stuff(id, interval) {
	const action = actions.get(id);

	// breakout condition
	if (action.status === 'stop') {
		return;
	}
	console.log('processing...');

	const response = await action.action();

	console.log('executing action onFinished...');
	action.onFinished(action.name, response);

	delay(interval).then(function callAgain() {
		do_stuff(id, interval);
	});
}

/*
// one way to run it:
do_stuff('1', 1000);

// to stop it
actions.get('1').status = 'stop';

*/




0 个答案:

没有答案