我在Javascript中对Promises相对较新,但最近爱上了他们的优雅,特别是在Bluebird图书馆。
这可能是一个新手问题,但我如何将正常同步函数转换为异步运行?例如,如果我想并行计算Math.random()*RANGE
三十次,那我怎么能用promises(在Q或Bluebird中)做到这一点?
答案 0 :(得分:2)
你做不到。 Promise不会“使代码并行”,它们只是为异步代码提供了更好的抽象 - 它们没有more power than callbacks。
同步代码将始终同步执行,并且 - 由于JavaScript的单线程特性 - 不可并行化。即使你给它一个回调,其执行是通过使用an actually async function推迟的,这只会将回调推迟到以后的事件循环切片,但不会使你的同步任务与其他任何东西并行执行 - 并赢得' t使它执行得更快。它可能有助于将长时间运行的代码分解成块(请参阅here或here),这可以使应用感觉更快。
您可以做的是在另一个线程(WebWorker,node cluster,...)上执行代码,并使用事件将结果传回。对于那些事件,你可以编写一个很好的承诺抽象;但严重的是 - 线程的开销太大而不能生成30个随机数。
答案 1 :(得分:2)
首先,承诺不会帮助您使代码并行运行。它们是在任务完成时运行其他代码或将此任务与其他任务协调的工具。但是让你当前的代码与其他代码并行运行与promises无关。
其次,采取同步任务并尝试使其更像是异步任务,除非它长时间运行以至于干扰其他任务的响应性,因此没什么优势(以及很多复杂性)操作。计算一组随机数不一定是那么长的任务。
如果您真的想要在浏览器中并行执行,那么您将使用WebWorkers,这是在基于浏览器的JavaScript中创建真正独立的执行线程的唯一方法。除了WebWorkers之外,浏览器中的javascript是单线程的,因此没有并行执行。可以在连续的setTimeout()
调用中执行小块代码,这将使代码执行与浏览器中正在进行的其他操作交织,并允许其他浏览器任务在运行另一个长时间运行的任务时保持响应。
您可以使用setTimeout()
Best way to iterate over an array without blocking the UI来查看以块为单位处理大型数组的示例,以允许其他内容在处理块之间运行。承诺可以添加到这样的事情中作为管理任务完成或管理其与其他任务的协调的方法,但承诺实际上并没有帮助你使它在块中工作。