Javascript等效于gevent.sleep(0)

时间:2013-12-30 22:36:47

标签: javascript python multitasking gevent

在Python中,有一个名为gevent的库可以实现协作式多任务处理。有时,让两个长时间运行的函数相互执行会很有用。例如:

def long_running_func1():
    while True:
        # processor intensive
        gevent.sleep()

gevent.sleep调用将任务置于睡眠状态。没有参数,它只会让执行到其他任务。

在浏览器中使用Javascript,我发现自己想要类似的东西,以便在处理器密集型工作之间,UI有机会更新。类似的东西:

var data = [];

setTimeout(function () {
    while (true) {
        // Update UI with data.slice(data.length - 5, 5)
        // gevent.sleep(0);
    }
}, 0);

setTimeout(function () {
    while (true) {
        // var value = computation;
        // data.append(value);
        // gevent.sleep(0);
    }
}, 0);

Javascript是否提供某种允许这种模式的多任务处理?

我一直在使用的模式是将上面的内容重写为:

var data = [];

function update_ui() {
    // Update UI with data.slice(data.length - 5, 5)
}

function repeatedly() {
    var value = computation;
    data.append();
    update_ui();
    setTimeout(repeatedly, 0);
}

repeatedly();

但随着代码变得越来越复杂,这种模式不可避免地涉及到更多与setTimeout链接的函数,而且它的可读性不高。

有比上面更好的模式吗?

1 个答案:

答案 0 :(得分:2)

Javascript是由大自然驱动的事件,但你总是在单个线程上工作。

IO是唯一始终处理异常的东西(浏览器javascript中没有阻塞IO功能)。

以块为单位拆分长计算,如果要进行长计算,请使用异步库为代码提供结构,并避免锁定UI。

https://github.com/caolan/async

类似的东西:

var LongTask = function() {
    this.state = 0;
    this.result = 'whatever';
};

LongTask.prototype.start = function(callback) {
    async.whilst(
        this._isFinished.bind(this),
        this._doChunk.bind(this),
        function(error) {
            callback(error, this.result);
        }
    );
};

LongTask.prototype._isFinished = function() {
    return this.state > 1000;
};

LongTask.prototype._doChunk = function(callback) {
    var chunkEnd = this.state + 10;
    while (this.state++ < chunkEnd) {
         .... do something ...
    }

    // In NodeJS, you would call process.nextTick(callback)
    setTimeout(callback, 0);
};

以后或其他文件

var task = new Task();
task.start(function(error, result) {
    // work is done without locking the whole process

});