I have a website which calculates various aspects of musical intonation. I would like to do a batch calculation in the console, but it seems that recursion is causing a problem because it needs to run a function (maybe?). I have a very large array called ratio
which holds many numerators and denominators. I would like to inject them into pre-existing variables called inputNum
and inputDen
and then run the underlying JS function doCalc()
that I have coded on the site, which takes the inputs and does various calculations with them. The result outputs into some div
fields on the page, which I just want to print in the log (to copy and paste into a spreadsheet). My code looks like this so far, after defining the large array of fractions 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();
Since it takes a non-negligible amount of time to do the calculation before displaying the results (I assume), I thought an async function would be the way to go, but I don't seem to be implementing it correctly. Otherwise, I would have done it with a simple while loop, but apparently setTimeout
won't work in that case.
As discussed in the comments, what you want to do should be possible, but it's a pretty awful way of writing this sort of functionality. Depending upon the DOM and global variables to do your work is pretty nasty.
If we start with something like this:
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>
We would eventually want to get to something like this:
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>
The big difference is that the calculation is done without worrying about the DOM. It is a pure function, and the code that uses it can use it to write to the console or to update the DOM.
Note also, though, that my first block does work. It's possible that if you changed your loop to this sort of structure that it will work for you. But it would then forever remain code difficult to test, difficult to extend, and difficult to understand.
The second format is much simpler.