【问题标题】:How can I execute an async function after another async function has finished executing in JS?在 JS 中执行完另一个异步函数后,如何执行异步函数?
【发布时间】:2021-08-26 13:33:39
【问题描述】:

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

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

我面临的问题是:

  1. 我正在尝试使用 promisified 函数获取地理位置。因此,如果使用 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);

【问题讨论】:

  • 嗯,完成后调用?
  • 所以你是说const { coords } = await getPosition(); 没有在等待回复?
  • 我记得这个练习(不是很久以前)是我开始理解回调概念的那个练习。在这种情况下,使用 Promises 时,请确保您了解 .thendeveloper.mozilla.org/en-US/docs/Web/JavaScript/Guide/…masteringjs.io/tutorials/fundamentals/then
  • 是的。我想在任何一种情况下获取数据,在获取用户位置之后或在获取用户位置时发生任何错误。
  • const fetchPro = method ? fetch(url, { method: "get" }) : fetch(url);

标签: javascript async-await promise asynchronous-javascript


【解决方案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() 之前执行。

【讨论】:

  • 这有帮助,但我怀疑 AJAX func() 是否会等待 getPosition() 返回响应?我现在有点困惑这两个异步函数将如何执行以及以何种顺序执行。你能帮我理解一下吗?
  • @GargiChaurasia,我在答案中添加了我的解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-06
  • 1970-01-01
  • 2019-12-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多