Javascript背景循环

前端之家收集整理的这篇文章主要介绍了Javascript背景循环前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

假设我们有一个loop.js文件

longLoop().then(res => console.log('loop result processing started'))
console.log('read file started')
require('fs').readFile(__filename,() => console.log('file processing started'))
setTimeout(() => console.log('timer fires'),500)

async function longLoop () {
  console.log('loop started')
  let res = 0
  for (let i = 0; i < 1e7; i++) {
    res += Math.sin(i) // arbitrary computation heavy operation
    if (i % 1e5 === 0) await null /* solution: await new Promise(resolve => setImmediate(resolve)) */
  }
  console.log('loop finished')
  return res
}

如果run(node loop.js)输出

loop started
read file started
loop finished
loop result processing started
timer fires
file processing started

当循环在后台运行时,如何重写此代码以读取和处理文件

我的解决方

我想出的是:

longLoop().then(res => console.log('loop result processing started'))
console.log('read file started')
require('fs').readFile(__filename,500)

async function longLoop () {
  let res = 0
  let from = 0
  let step = 1e5
  let numIterations = 1e7
  function doIterations() {
    //console.log(from)
    return new Promise(resolve => {
      setImmediate(() => { // or setTimeout
        for (let i = from; (i < from + step) && (i < numIterations); i++) {
          res += Math.sin(i)
        }
        resolve()
      })
    })
  }
  console.log('loop started')
  while (from < numIterations) {
    await doIterations()
    from += step
  }
  console.log('loop finished')
  return res
}

确实记录了:

loop started
read file started
file processing started
timer fires
loop finished
loop result processing started

有更简单,更简洁的方法吗?我的解决方案有什么缺点?

最佳答案
你的代码的第一个版本阻止进一步处理的原因是await获得了一个立即解析的promise(值null被包装在一个promise中,好像你确实等待了Promise.resolve(null)).这意味着await之后的代码将在当前“任务”期间恢复:它只是推动任务队列中的微任务,这将在同一任务中消耗.您挂起的所有其他异步内容都在任务队列中等待,而不是微任务队列.

这是setTimeout的情况,也适用于readFile.它们的回调在任务队列中处于待处理状态,因此不会优先于等待生成的mircrotasks.

因此,您需要一种方法来等待将任务放入任务队列而不是微任务队列.这可以通过向它提供不会立即解决的承诺来实现,但只能在当前任务之后解析.

您可以使用…. setTimeout引入延迟:

const slowResolve = val => new Promise(resolve => setTimeout(resolve.bind(null,val),0));

您可以使用await调用函数.这是一个使用图像加载而不是文件加载的片段,但原理是相同的:

const slowResolve = val => new Promise(resolve => setTimeout(resolve.bind(null,0));

longLoop().then(res => 
    console.log('loop result processing started'))

console.log('read file started')

fs.onload = () => 
    console.log('file processing started');
fs.src = "https://images.pexels.com/photos/34950/pexels-photo.jpg?h=350&auto=compress&cs=tinysrgb";

setTimeout(() => console.log('timer fires'),500)

async function longLoop () {
  console.log('loop started')
  let res = 0
  for (let i = 0; i < 1e7; i++) {
    res += Math.sin(i) // arbitrary computation heavy operation
    if (i % 1e5 === 0) await slowResolve(i);
  }
  console.log('loop finished')
  return res
}
原文链接:https://www.f2er.com/js/429190.html

猜你在找的JavaScript相关文章