Javascript异步承诺作为宏任务

时间:2019-12-06 04:54:19

标签: javascript concurrency promise async-await

在我的应用程序中,有时我会通过许诺排队太多微任务,以至于UI会被阻塞并且无法响应。

有什么办法可以类似方式将它们作为宏任务排队吗? 使用setTimeout()可以很好地工作,UI可以再次响应,但是代码非常丑陋,使我陷入回调地狱。

谢谢!

2 个答案:

答案 0 :(得分:1)

如果由于承诺以比许多其他类型的事件更高的优先级运行,您正在排队足够的诺言以使UI饿死,则您可能只是试图一次运行太多异步操作或以某种方式编写了代码创造了太多的承诺,这些承诺必须被安排并与其他事物竞争。

解决此问题的正确方法可能是修复您的代码,因此它不会尝试创建很多承诺。仅当您向我们展示实际上导致该问题的代码时,我们才能为您提供帮助。

  

有什么办法可以将它们作为宏任务以类似的方式排队吗?

内置于JS的promise实现无法使它如何配置promise的计划,因此它们很难使用其优先级高于事件队列中许多其他事物的微任务,因此您无法更改它。

您可以获得一个第三方库(该库是在JS内置内置Promise之前用于Promise使用的),无法访问微任务系统,并且会使用setTimeout()或{{1 }}。但是,您必须以某种方式确保所有代码都已切换到该第三方库,而不是无意中使用了内置实现。

老实说,这感觉像是完全破解,不是我要追求的解决方案。单线程JS是一个协作系统。为了使UI保持响应状态,它依赖于一些合作,而不是为了使UI保持响应状态而对主线程进行优先级高或长时间运行的操作。

在某些情况下,您可以将一些代码移出到webWorker(如果是浏览器),或者移到WorkerThread(如果这是node.js),并将麻烦的代码移出与UI相同的事件循环。

但是,最好的解决方案可能是驯服您的Promise驱动的代码,这样它就不会连续运行过多的Promise计划的事情,而这会干扰UI。如果您向我们展示了实际上导致问题的承诺代码,我们只能为您提供一些有关如何做到这一点的想法。

答案 1 :(得分:1)

创建承诺后,该承诺将立即执行。因此,应将承诺创建排队。执行此类操作的最佳软件包之一称为async。撰写本文时,它在Github中拥有26.2万颗星。

查看他们文档中的queue example,以更好地了解其工作原理:

// create a queue object with concurrency 2
var q = async.queue(function(task, callback) {
    console.log('hello ' + task.name);
    callback();
}, 2);

// assign a callback
q.drain(function() {
    console.log('all items have been processed');
});
// or await the end
await q.drain()

// assign an error callback
q.error(function(err, task) {
    console.error('task experienced an error');
});

// add some items to the queue
q.push({name: 'foo'}, function(err) {
    console.log('finished processing foo');
});
// callback is optional
q.push({name: 'bar'});

// add some items to the queue (batch-wise)
q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) {
    console.log('finished processing item');
});

// add some items to the front of the queue
q.unshift({name: 'bar'}, function (err) {
    console.log('finished processing bar');
});