我正在使用 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 函数的第一行,但没有帮助。我看到输出中的对象和数组都是空的。为什么?
鼓励 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 });
}
}