Объединение двух обещаний с использованием обещания. - PullRequest
2 голосов
/ 18 апреля 2020

У меня есть два обещания от двух разных вызовов API в моем приложении VUE JS, я думал, может быть, оба могут быть объединены с использованием подхода promise.all()? Если да, то как я могу это сделать?

API. js

async function getForecast(lat, lon) {
  try {
    const response = await fetch(`${WEATHER_API_URL}&lat=${lat}&lon=${lon}`);
    return await response.json();
  } catch (error) {
    console.log(error);
  }
}

async function getAddress(lat, lon) {
  try {
    const response = await fetch(`${ADDRESS_API_URL}&lat=${lat}&lon=${lon}`);
    return await response.json();
  } catch (error) {
    console.log(error);
  }
}

Приложение. vue

loadWeather(lat, lon) {
  API.getAddress(lat, lon).then(result => {
    this.address = result.name;
  });
  API.getForecast(lat, lon).then(result => {
    this.forecast = result;
  });
}

Ответы [ 4 ]

2 голосов
/ 19 апреля 2020

В дополнение к существующим ответам, это когда async..await становится полезным, так как он уже используется в других функциях. Массив, в который Promise.all разрешается, может быть деструктурирован:

async loadWeather(lat, lon) {
  const [address, forecast] = await Promise.all([
    API.getAddress(lat, lon),
    API.getForecast(lat, lon)
  ]);
  this.address = address.name;
  this.forecast = forecast;
}
1 голос
/ 18 апреля 2020

Во-первых, решите, хотите ли вы, чтобы обещание не было выполнено в случае сбоя любого из двух вызовов API. Promise.all не удастся в этом случае, Promise.allSettled не будет. Это зависит от того, что вы хотите для своего приложения.

Чтобы объединить, вы можете сделать следующее:

loadWeather(lat, lon) {
  Promise.all([
    API.getAddress(lat, lon),
    API.getForecast(lat, lon)
  ]).then(([addressResult, forecastResult]) => {
    this.address = addressResult.name;
    this.forecast = forecastResult;
  });
}

Promise.all возвращает массив результатов. Это имеет смысл, если вы считаете, что передаете ему массив обещаний.

1 голос
/ 18 апреля 2020

Да, вы можете написать

loadWeather(lat, lon) {
  Promise.all([
    API.getAddress(lat, lon),
    API.getForecast(lat, lon),
  ]).then(([addressResult, forecastResult]) => {
    this.address = addressResult.name;
    this.forecast = forecastResult;
  });
}

Однако в действительности это не кажется необходимым, поскольку обе функции уже обрабатывают ошибки, и, похоже, нет причины, по которой присваивания свойств должны дождитесь оба обещания выполнить.

1 голос
/ 18 апреля 2020

Да, вы можете использовать Promise.all для объединения ваших звонков. Ниже показано, как вы можете это сделать ...

(я использую setTimouts вместо ваших запросов на выборку)

const functionA = async () => {
  await new Promise(resolve => {
    setTimeout(() => { resolve(); }, 2000);
  });

  return "A";
};

const functionB = async () => {
  await new Promise(resolve => {
    setTimeout(() => { resolve(); }, 3000);
  });

  return "B";
};

const getResults = async () => {
  const result = await Promise.all([functionA(), functionB()]);
  return result;
};

getResults().then(result => console.log(result));

Просмотр https://codesandbox.io/s/blue-lake-qupp7?file= / src / index . js

Чтобы перевести это на ваш пример, мы можем поэтому сделать ...

// promise
function loadWeather(lat, lon) {
  Promise.all([
    API.getAddress(lat, lon),
    API.getForecast(lat, lon)
  ]).then(([address, forecast]) => {
    this.address = address.name;
    this.forecast = forecast;
  });
}

// or async/await
async function loadWeather(lat, lon) {
  const [address, forecast] = await Promise.all([
    API.getAddress(lat, lon),
    API.getForecast(lat, lon)
  ]);

  this.address = address.name;
  this.forecast = forecast;
}
...