当主抓取的结果是循环中的特定值时,如何使用 JavaScript 等待二级抓取结果?

How to wait for secondary fetched result with JavaScript when the result of a primary fetch is a specific value within a loop?

在一个名为 javascript functiontimer 中,我需要使用多个 json API 调用来更新 UI。 这是一个电能表,将实际消耗的相功率存储在 3 个不同的寄存器中。除了负值(太阳能电池板的能量)外,返回的能量存储在其他 3 个寄存器中(作为正值)。 If相功率为0,需要取交替相功率寄存器

Loop 3 times
  Fetch A at api1
  If A=0 Then
    Fetch A at api2
  Display A
  Display min(A)
  Display max(A)
  Display trend
  Even more display stuff I don't want to duplicate

我设法获取了该值,但是无法获取替代的获取值以在 fetch 块下方继续存在。获取 api2 时显示 A = 0(returns 不是 0)。

我尝试了 asyncawait,比如 。因此更改以下代码中的 2 行:

async function update()
…
                        await fetch(APIGW+"v1/sm/fields/power_returned_l"+myPhase)

这导致:

Uncaught SyntaxError: await is only valid in async functions and async generators
Uncaught ReferenceError: update is not defined

如何在执行此 if (nvKW == 0 ) 块时使底部 document.getElementById(以及下面的大量 UI 内容)等待第 2 级(不是第 2 循环)获取?

function update()
{
    var phase;
    for( let phase = 1 ; phase <= PHASES ; phase++ )
    {
        fetch(APIGW+"v1/sm/fields/power_delivered_l"+phase)
        .then(response => response.json())
        .then(json => 
          {
            for( let j in json.fields ){
                if (json.fields[j].name.startsWith("power_delivered_l"))
                {
                    myPhase = Number(json.fields[j].name.replace('power_delivered_l',''));

                    let nvKW=Number(json.fields[j].value)
                    if (nvKW == 0 ) // check if power is generated
                    {
                        fetch(APIGW+"v1/sm/fields/power_returned_l"+myPhase)
                        .then(response => response.json())
                        .then(json2 => 
                          {
                            for( let jr in json2.fields ){
                                if (json2.fields[jr].name.startsWith("power_returned_l"))
                                {
                                    let nvKW=-1*Number(json2.fields[jr].value)
                                    console.log(json2.fields[jr].name+" = "+ nvKW.toString()) // here nvKW contains a value
                                }
                            }
                          }
                        );
                    }

                    console.log("nvKW = "+ nvKW.toString()) // 1st level fetch = 0 and 2nd level fetch != 0 then nvKW is still 0 here, where I need the value from the 2nd level fetch
                    document.getElementById(json.fields[j].name).innerHTML = nvKW.toFixed(1);
                    // a lot more ui stuff is done below

然后使用 else:

function updateUIwithA(A){
   //Do whatever you need to update UI from A
   //document.getElementById("fieldNameForDisplayAValue").innerHTML = getValue(A);
   //document.getElementById("fieldNameForDisplayAMin").innerHTML = getMin(A);
   //document.getElementById("fieldNameForDisplayAMax").innerHTML = getMax(A);
   //document.getElementById("fieldNameForDisplayAverage").innerHTML = getAverage(A);
}


                    ...
                    let nvKW=Number(json.fields[j].value)
                    if (nvKW == 0 ) // check if power is generated
                    {
                        //First power is 0, then fetch the second power
                        fetch(APIGW+"v1/sm/fields/power_returned_l"+myPhase)
                        .then(response => response.json())
                        .then(json2 => 
                          {
                            for( let jr in json2.fields ){
                                if (json2.fields[jr].name.startsWith("power_returned_l"))
                                {
                                    //Show second power
                                    let nvKW2=-1*Number(json2.fields[jr].value)
                                    console.log(json2.fields[jr].name+" = "+ nvKW.toString()) // here nvKW contains a value
                                    updateUIwithA(json2);
                                }
                            }
                          }
                        );
                    } else {
                       //First power is not 0, so show the current value and ignore second fetch
                       updateUIwithA(json);
                    }

在条件承诺上使用 .then() 语法:

json => {
    const field = getFieldByName(json, "power_delivered_l");
    const myPhase = field.name.replace('power_delivered_l','');
    (field.value == 0 // check if power is generated
      ? fetch(APIGW+"v1/sm/fields/power_returned_l"+myPhase)
        .then(response => response.json())
        .then(json2 => getFieldByName(json2, "power_returned_l", -1))
      : Promise.resolve(field)
    ).then(({name, value: nvKW}) => {
         console.log(`${name} = ${nvKW}`)
         document.getElementById(json.fields[j].name).innerHTML = nvKW.toFixed(1);
         // a lot more ui stuff is done below
    });
}

使用async/await:

async json => {
    let field = getFieldByName(json, "power_delivered_l");
    if (field.value == 0) // check if power is generated
        const myPhase = field.name.replace('power_delivered_l','');
        const response = await fetch(APIGW+"v1/sm/fields/power_returned_l"+myPhase);
        const json2 = await response.json())
        field = getFieldByName(json2, "power_returned_l", -1))
    }
    const {name, value: nvKW} = field;
     console.log(`${name} = ${nvKW}`)
     document.getElementById(json.fields[j].name).innerHTML = nvKW.toFixed(1);
     // a lot more ui stuff is done below
}

两者都使用辅助函数

function getFieldByName(json, prefix, factor = 1) {
    for (const field of json.fields) {
        if (field.name.startsWith(prefix)) {
             return {
                 name: field.name,
                 value: factor * Number(field.value)
             };
        }
    }
    throw new Error(`Did not find field '${prefix}' in the JSON`);
}