Как передавать данные между обещаниями асинхронно? - PullRequest
0 голосов
/ 08 мая 2020

Я хочу получить из бэкэнда несколько данных и обработать их в конце, когда они будут загружены. Прямо сейчас, когда выполняется этот код, данные data1 и data2 не определены. Я хочу их дождаться, но не знаю, как сохранить свой код в чистоте. Я не уверен, что Promise.all () подойдет здесь, потому что мне нужно сохранить значение data1 и data2, и я не могу написать общий код для разрешения для Promise.all ().

return new Promise( (resolve,reject) => {
 let data1;
 let data2;

 let url1 = "http://fakeapi.com/getData1";
 fetch(url1)
 .then(res => res.json())
 .then(data => data1SpecificAction())
 .then(data => data1 = data)
 .catch("cannot fetch data1")

 let url2 = "http://fakeapi.com/getData2";
 fetch(url2)
 .then(res => res.json())
 .then(data => data2 = data)
 .catch("cannot fetch data2")

 if(data1 && data2) {
  resolve()
 }
 else {
  reject()
 }
}

Как я могу исправить этот фрагмент?

Ответы [ 2 ]

1 голос
/ 08 мая 2020

Вам не нужно много того, что у вас есть в вашем вопросе или в вашем ответе. Вы можете просто сделать это:

const url1 = "http://fakeapi.com/getData1";
const url2 = "http://fakeapi.com/getData2";
return Promise.all([
    fetch(url1).then(res => res.json()).then(data1SpecificAction), 
    fetch(url2).then(res => res.json())
]).then([data1, data2] => {
    if (data1 && data2) return;         // resolve
    // reject with appropriate error
    let msg = data1 ? "missing data2" : "missing data1";
    throw new Error(msg);
});

То, что вам не нужно делать в вопросе и ответе:

  1. Не оборачивайте существующие обещания в другое обещание, созданное вручную. Это считается анти-шаблоном, поскольку созданное вручную обещание просто не нужно. Вы можете просто вернуть обещания, которые у вас уже есть.
  2. Не назначайте результат .then() переменной с более высокой областью действия. Хотя иногда для этого есть причины, это не одна из них и обычно является предупреждением о том, что вы делаете что-то неправильно.

Интерфейс fetch() вызывает некоторые неудобства которые я часто нахожу полезными для вспомогательной функции (например, статус 404 разрешает, а не отклоняет):

function fetchJson(...args) {
    return fetch(...args).then(res => {
        if (!res.ok) throw new Error(`Got ${res.status} status`);
        return res.json();
    });
}

const url1 = "http://fakeapi.com/getData1";
const url2 = "http://fakeapi.com/getData2";
return Promise.all([
    fetchJson(url1).then(data1SpecificAction), 
    fetchJson(url2)
]).then([data1, data2] => {
    if (data1 && data2) return;         // resolve
    // reject with appropriate error
    let msg = data1 ? "missing data2" : "missing data1";
    throw new Error(msg);
});

И в вашем конкретном случае c, когда вы хотите отклонить, если результат ложно, вы даже можете сделать это:

function fetchJsonCheck(...args) {
    return fetch(...args).then(res => {
        if (!res.ok) throw new Error(`Got ${res.status} status`);
        return res.json();
    }).then(result => {
        if (!result) throw new Error("empty result");
        return result;
    });
}

const url1 = "http://fakeapi.com/getData1";
const url2 = "http://fakeapi.com/getData2";
return Promise.all([
    fetchJsonCheck(url1).then(data1SpecificAction), 
    fetchJsonCheck(url2)
]);
0 голосов
/ 08 мая 2020

Решение заключалось в том, чтобы поместить мое конкретное действие c в другие обещания и использовать обещание. Все

return new Promise( (resolve,reject) => {
 let data1;
 let data2;

 let promise1 = new Promise( (resolve,reject) => {
  let url1 = "http://fakeapi.com/getData1";
  fetch(url1)
  .then(res => res.json())
  .then(data => data1SpecificAction())
  .then(data => { 
   data1 = data;
   resolve()
   }
  .catch(()=>reject("cannot fetch data1"))
 })

 let promise 2 = new Promise( (resolve,reject) => {
  let url2 = "http://fakeapi.com/getData2";
  fetch(url2)
  .then(res => res.json())
  .then(data => { 
   data2 = data;
   resolve()
   }
  )
  .catch(()=>reject("cannot fetch data2"))
 })

 Promise.all([promise1,promise2])
 .then(
  () => {
   if(data1 && data2) {
    resolve()
   }
   else {
     reject()
   }
  }
 )

здесь - это ссылка, объясняющая, как передавать данные между обещаниями.

...