1

我正在尝试使用 vanilla JS 和 API 创建一个天气报告应用程序。我的目标是:

  1. 当网页完成加载时,我想询问用户他们的位置。
  2. 如果用户接受请求 我想使用浏览器 api 获取他们的坐标并存储纬度和经度,然后运行另一个异步函数,该函数将使用这些纬度和经度数据从 OpenWeather api 获取数据。湾。相应地更新 UI。
  3. 如果用户阻止请求:我仍想从 OpenWeather api 获取数据,但这次使用默认的纬度和经度值(例如巴黎)

我面临的问题是:

  1. 我正在尝试使用承诺功能获取地理位置。因此,如果使用 async/await,这将在异步函数中执行,但我无法一个接一个地运行两个异步函数,以便它可以使用先前执行的函数的响应数据。
  2. 如果用户在浏览器中阻止该位置,该函数将被拒绝并执行catch块,那么我应该将天气api函数放在catch块中以使用默认的经纬度值还是做其他事情?
  3. 据我所知,连续执行多个异步函数并不能保证结果将以相同的顺序出现,因此有时天气 api 函数会使用默认的 lat 和 lon 值成功地从 api 获取数据,而不是等待用户的位置。如何修复代码以便获得所需的输出?

我是 JS 和 SO 的新手,所以如果需要任何澄清,请告诉我。顺便说一句,我还分享了代码以便更好地理解。抱歉发了这么长的帖子:(

const WEATHER_API_KEY = "f19d6e315954bfb123e794ab55aa28c4";

const state = {
    location: {
        //setting default location of paris
        lat: 48.8566969,
        lng: 2.3514616
    }
};

///////////////////////////////////////
// Geolocation api function
const options = {
    enableHighAccuracy: true,
    timeout: 5000,
    maximumAge: 0
};

// Getting location using geolocation API
const getPosition = function () {
    return new Promise(function (resolve, reject) {
        navigator.geolocation.getCurrentPosition(resolve, reject, options);
    });
};

//////////////////////////////////////////////
// Helper function to fetch data from api
const TIMEOUT_SEC = 5;

const timeout = function (s) {
    return new Promise(function (_, reject) {
        setTimeout(function () {
            reject(new Error(`Request took too long! Timeout after ${s} second`));
        }, s * 1000);
    });
};

//get json data from api
export const AJAX = async function (url, method = undefined) {
    try {
        const fetchPro = method
            ? fetch(url, {
                    method: "get"
              })
            : fetch(url);

        const res = await Promise.race([fetchPro, timeout(TIMEOUT_SEC)]);
        const data = await res.json();

        if (!res.ok) throw new Error(`${data.message} (${res.status})`);
        return data;
    } catch (err) {
        throw err;
    }
};

//////////////////////////////
// Executing functions and fetching data

const loadData = async function () {
    try {
        const { coords } = await getPosition();
        const { latitude, longitude } = coords;
        state.location.lat = latitude;
        state.location.lng = longitude;
        const weatherData = await AJAX(
            `https://api.openweathermap.org/data/2.5/onecall?lat=${state.location.lat}&lon=${state.location.lng}&&units=metric&appid=${WEATHER_API_KEY}`
        );
        console.log(weatherData);
    } catch (err) {
        console.error("Error occured!!", err);
    }
};

window.addEventListener("load", loadData);

4

1 回答 1

1

您可以在 getPosition() 中捕获错误并返回默认状态。

const WEATHER_API_KEY = "f19d6e315954bfb123e794ab55aa28c4";

const state = {
  location: {
    //setting default location of paris
    latitude: 48.8566969,
    longitude: 2.3514616,
  },
};

///////////////////////////////////////
// Geolocation api function
const options = {
  enableHighAccuracy: true,
  timeout: 5000,
  maximumAge: 0,
};

// Getting location using geolocation API
const getPosition = async function () {
  try {
    const { coords } = await new Promise(function (resolve, reject) {
      navigator.geolocation.getCurrentPosition(resolve, reject, options);
    });
    return coords;
  } catch (err) {
    console.log(err);
    return state.location;
  }
};

//////////////////////////////////////////////
// Helper function to fetch data from api
const TIMEOUT_SEC = 5;

const timeout = function (s) {
  return new Promise(function (_, reject) {
    setTimeout(function () {
      reject(new Error(`Request took too long! Timeout after ${s} second`));
    }, s * 1000);
  });
};

//get json data from api
export const AJAX = async function (url, method = undefined) {
  try {
    const fetchPro = method
      ? fetch(url, {
          method: "get",
        })
      : fetch(url);

    const res = await Promise.race([fetchPro, timeout(TIMEOUT_SEC)]);
    const data = await res.json();

    if (!res.ok) throw new Error(`${data.message} (${res.status})`);
    return data;
  } catch (err) {
    throw err;
  }
};

//////////////////////////////
// Executing functions and fetching data

const loadData = async function () {
  try {
    const { latitude, longitude } = await getPosition();
    const weatherData = await AJAX(
      `https://api.openweathermap.org/data/2.5/onecall?lat=${latitude}&lon=${longitude}&&units=metric&appid=${WEATHER_API_KEY}`
    );
    console.log(weatherData);
  } catch (err) {
    console.error("Error occured!!", err);
  }
};

window.addEventListener("load", loadData);

编辑解释:

下面的异步/等待:

async function run() {
  try {
    const { latitude, longitude } = await getPosition();
    const weatherData = await AJAX(
      `https://api.openweathermap.org/data/2.5/onecall?lat=${latitude}&lon=${longitude}&&units=metric&appid=${WEATHER_API_KEY}`
    );
    console.log(weatherData);
  } catch (err) {
    console.log(err);
  }
}

可以写成

getPosition()
  .then(({ latitude, longitude }) => {
    AJAX(`lat=${latitude}&lon=${longitude}`).then(weatherData => {
      console.log(weatherData);
    });
  })
  .catch(console.log);

这就是为什么 getPosition() 会在 AJAX() 之前执行。

于 2021-08-26T14:07:04.487 回答