异步函数的主体执行时间早于另一个异步函数完成执行

问题描述 投票:0回答:1

我正在使用 JavaScript fetch api 制作天气预报应用程序。我想从 processFormat 函数接收数据并在 showResults 函数中使用该数据,但不能,因为由于某种原因 showResults 函数的执行早于 processFormat 函数

const processFormat = async (range) => {
    let getCityUrl = `http://api.openweathermap.org/geo/1.0/direct?q=${city}&limit=${limit}&appid=${apiKey}`;
    //resultStates.length = 0; 
    fetch(getCityUrl)
    .then((response) => {
        return response.json();
    })
    .then((data) => {
        data.forEach((item) => {
            console.log(item);
            resultStates.push(item.state);
            resultObj[item.state] = {
                'lat': item['lat'],
                'lon': item['lon']
            };
        });
    })
    .catch(rejected => {
        console.log(rejected);
    })
    console.log(resultObj);
};
//...
const showResults = async (range) => {
    await processFormat(range);
    for (let i=0; i<Object.keys(resultObj).length; i++) {
        resultStates.push(Object.keys(resultObj)[i]);
    }
    console.log(`resultStates: ${resultStates}`)
    if (resultStates.length === 0) {
        resultSection.textContent = `Failed to find your city: ${city}. Try another city`;
        setTimeout(() => {
            resultSection.textContent = '';
            clickedSearch = 0;
        }, 5000);
    }
    else {
        //...
    }
};

我尝试将

await processFormat(range);
放在 processFormat 函数的第一行,但没有帮助。我看到输出中的对象和数组都是空的。为什么?

javascript asynchronous async-await fetch
1个回答
0
投票

鼓励 OP 放弃真正需要的外部范围引用的突变。每个函数应该负责处理数据/状态,这些数据/状态要么是在函数本身内创建的,要么是作为另一个函数调用的结果而获取的。因此,通过减少这种依赖关系,函数可以更好地进行测试和维护。此外,OP 还可能考虑完全切换到 async-await 语法。它可能比承诺的链式

then
-
catch
方法更容易阅读/理解。

OP 示例代码的重构版本可能类似于以下提供的变体......

async function processFormat({ city, limit, apiKey }) {
  let response, data, error = null;
  try {

    response = await fetch(
      `http://api.openweathermap.org/geo/1.0/direct?q=${city}&limit=${limit}&appid=${apiKey}`;
    );
    data = await response.json();

  } catch(exception) {

    error = exception;
  }
  return [
    error,
    (error !== null) && data

      .reduce(({ stateNames, stateLookup }, { state, lat, lon }) => {

        stateNames.push(state);
        stateLookup[state] = { lat, lon };

        return { stateNames, stateLookup };

      }, { stateNames: [], stateLookup: {} }) || data,
  ];
}

async function showResults({ city, limit, apiKey }) {
  const [
    error, result,
  ] =
    await processFormat({ city, limit, apiKey });

  if (error === null) {

    console.log(`'processFormat' failed with error ... ${ error }.`);

  } else if (result.stateNames.length === 0) {

    console.log(`Failed to find your city: ${ city }.`);
  } else {
    console.log({ stateLookup: result.stateLookup });
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.