控制台递归,批量计算(JS)

Recursion in console, batch calculation (JS)

我有一个网站可以计算音乐语调的各个方面。我想在控制台中进行批量计算,但递归似乎导致了问题,因为它需要 运行 一个函数(也许?)。我有一个名为 ratio 的非常大的数组,其中包含许多分子和分母。我想将它们注入到名为 inputNuminputDen 的预先存在的变量中,然后是 运行 我在网站上编写的底层 JS 函数 doCalc(),它采用输入并用它们进行各种计算。结果输出到页面上的一些 div 字段,我只想在日志中打印(复制并粘贴到电子表格中)。到目前为止,我的代码看起来像这样,在定义了大的分数数组 ratio.

之后
var i = 0;                  

async function loop() {   
    inputNum = ratio[i][0];
    inputDen = ratio[i][1];
    await doCalc();       
    console.log(document.getElementById("notationOutput").innerHTML+" "+document.getElementById("noteName").innerHTML);   
    i++;                   
    if (i < ratio.length) {           
        loop();             
    }                      
}

loop(); 

由于在显示结果之前进行计算需要花费不可忽略的时间(我假设),我认为异步函数是可行的方法,但我似乎没有实现它正确。否则,我会用一个简单的 while 循环来完成它,但显然 setTimeout 在那种情况下不起作用。

您是否尝试过将 await 添加到 loop() 调用中,该调用在 if 内部调用,如下所示

var i = 0;                  

async function loop() {   
    inputNum = ratio[i][0];
    inputDen = ratio[i][1];
    await doCalc();       
    console.log(document.getElementById("notationOutput").innerHTML+" "+document.getElementById("noteName").innerHTML);   
    i++;                   
    if (i < ratio.length) {           
        await loop();  // Adding await here           
    }                      
}

loop(); 

(或)

作为自调用

(async function loop() {   
    inputNum = ratio[i][0];
    inputDen = ratio[i][1];
    await doCalc();       
    console.log(document.getElementById("notationOutput").innerHTML+" "+document.getElementById("noteName").innerHTML);   
    i++;                   
    if (i < ratio.length) {           
        await loop();  // Adding await here           
    }                      
})();

your reference 的类似示例 - 滚动到 async/await 递归 示例函数的末尾。

正如评论中所讨论的那样,你想做的事情应该是可能的,但这是编写此类功能的一种非常糟糕的方式。依靠 DOM 和全局变量来完成你的工作是非常讨厌的。

如果我们从这样的事情开始:

const doCalc = () => {
  const num = Number (document .getElementById ('numerator') .value)
  const den = Number (document .getElementById ('denominator') .value)
  // do some real work here
  const notationOutput = `${num}/${den}`
  const noteName = `${num}--${den}`
  document .getElementById ("notationOutput") .innerHTML = notationOutput
  document .getElementById ("noteName") .innerHTML = noteName
}

document .getElementById ('numerator') .onchange = doCalc
document .getElementById ('denominator') .onchange = doCalc

const logAll = (ratios) =>
  ratios 
    .forEach (([num, den]) => {
       document .getElementById ('numerator') .value = String (num)
       document .getElementById ('denominator') .value = String (den)
       doCalc()
       const notationOutput = document .getElementById ("notationOutput") .innerHTML
       const noteName = document .getElementById ("noteName") .innerHTML
       console.log(`${notationOutput} ${noteName}`)
    })

const ratios = [[5, 3], [7, 4], [3, 2], [13, 1]]

document.getElementById('batch') .onclick = (evt) => logAll (ratios)
<p>
  <label>Numerator: <input id="numerator" /></label>
  <label>Denominator: <input id="denominator" /></lbael>
</p>
<p>Notation Output <span id="notationOutput"></span></p>
<p>Note Name <span id="noteName"></span></p>
<p><button id="batch">Run Batch</button></p>


我们最终会想要达到这样的目的:

const doCalc = ([num, den]) => {
  // do some real work here
  return {
    notationOutput: `${num}/${den}`,
    noteName: `${num}--${den}`
  }
}

const change = (evt) => {
  const num = Number (document .getElementById ('numerator') .value)
  const den = Number (document .getElementById ('denominator') .value)
  const {notationOutput, noteName} = doCalc ([num, den])
  document .getElementById ("notationOutput") .innerHTML = notationOutput
  document .getElementById ("noteName") .innerHTML = noteName
}

document .getElementById ('numerator') .onchange = change
document .getElementById ('denominator') .onchange = change

const logAll = (ratios) =>
  ratios 
    .map (doCalc) 
    .forEach (
      ({notationOutput, noteName}) => console.log(`${notationOutput} ${noteName}`)
    )

const ratios = [[5, 3], [7, 4], [3, 2], [13, 1]]

document.getElementById('batch') .onclick = (evt) => logAll (ratios)
<p>
  <label>Numerator: <input id="numerator" /></label>
  <label>Denominator: <input id="denominator" /></lbael>
</p>
<p>Notation Output <span id="notationOutput"></span></p>
<p>Note Name <span id="noteName"></span></p>
<p><button id="batch">Run Batch</button></p>

最大的区别在于计算完成时无需担心 DOM。它是一个纯函数,使用它的代码可以使用它写入控制台或更新 DOM.


另请注意,我的第一个块确实有效。如果您将循环更改为这种结构,它可能对您有用。但它会永远保持代码难以测试、难以扩展和难以理解。

第二种格式就简单多了。