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

У меня есть одно обещание, которое зависит от возвращаемого значения другого обещания. Я успешно передаю это значение во второе обещание, но есть дополнительные данные, созданные в первом обещании, которые я хотел бы получить во втором обещании как-то .

Вот мой код :

const getAlbumInfo = async (album, artist) => {
        let hostname = 'http://www.musicbrainz.org';
        let path = `/ws/2/release-group/?query=release:${album}%20AND%20artist:${artist}&fmt=json`;
        let res = await fetch(hostname + path);
        return res.json();
};


const getAlbumArt = async (albumInfo) => {
    let res = await fetch(`${albumInfo.url}`);
    return res.json();
};    


let artist = '', album = '';

getAlbumInfo(album, artist)
    .then((res) => {
        const metadata = {
            album: res['album'],
            artist: res['artist'],
            url: res['url']
        };

        return getAlbumArt(metadata);
    })
    .then((res) => {
        console.log(res);  // prints result from getAlbumArt

        // I also need the contents of metadata here
    })
    .catch(e => { console.error(e); });

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

Поскольку я возвращаю / передаю метаданные во второе обещание, я попытался использовать Object.assign() внутри getAlbumArt() для объединения метаданных и получить результат, но это не сработало.

Ответы [ 4 ]

1 голос
/ 19 февраля 2020

await для второго обещания, а затем вернуть оба к следующему блоку .then. Используйте деконструкцию для более простого варианта использования:

getAlbumInfo(album, artist)
    .then(async ({album, artist, url}) => {
        const metadata = {album, artist, url};
        const arts = await getAlbumArt(metadata);

        return {arts, metadata};
    })
    .then(({arts, metadata}) => {
        // You have both here 
    })
    .catch(console.log);

В качестве альтернативы, все это действие может быть внутри функции async:

const getAlbum = async (album, artist) => {
  const info = await getAlbumInfo(album, artist);
  const metadata = {
    album: info.album,
    artist: info.artist,
    url: info.url,
  };
  const arts = await getAlbumArt(metadata);

  // everything is available;
};
1 голос
/ 19 февраля 2020

Поскольку вы могли бы использовать async/await, мы могли бы решить и эту проблему. Лучше использовать async/await вместо того, чтобы смешивать его с Promise.

Для этого нам нужно IIFE

(async () => { // define IIFE
  try { // try-catch to ensure error is catched
    const res = await getAlbumInfo(album, artist);

    const metadata = {
      album: res["album"],
      artist: res["artist"],
      url: res["url"]
    };

    const res2 = await getAlbumArt(metadata);

    console.log(res2);
    console.log(metadata);

  } catch (error) {
    console.error(error);
  }
})();

Надеюсь, это поможет

1 голос
/ 19 февраля 2020

Есть несколько способов сделать это, вы можете использовать await:

const getAlbumInfo = async(album, artist) => {
  let hostname = 'http://www.musicbrainz.org';
  let path = `/ws/2/release-group/?query=release:${album}%20AND%20artist:${artist}&fmt=json`;
  let res = await fetch(hostname + path);
  return res.json();
};


const getAlbumArt = async(albumInfo) => {
  let res = await fetch(`${albumInfo.url}`);
  return res.json();
};


let artist = '',
  album = '';

const getAll = async() => {
  const res1 = await getAlbumInfo(album, artist);
  const metadata = {
    album: res['album'],
    artist: res['artist'],
    url: res['url']
  };
  const res2 = await getAlbumArt(metadata);

  // here you have access to both responses (res1 and res2) and the created metadata object.
}

Если вы используете это, вы должны обернуть вызовы в try..catch...

Другой вариант будет передавать метаданные из второго обещания вместе с ответом:

const getAlbumInfo = async(album, artist) => {
  let hostname = 'http://www.musicbrainz.org';
  let path = `/ws/2/release-group/?query=release:${album}%20AND%20artist:${artist}&fmt=json`;
  let res = await fetch(hostname + path);
  return res.json();
};


const getAlbumArt = async(albumInfo) => {
  let res = await fetch(`${albumInfo.url}`);
  res = await res.json();
  return {
    res,
    albumInfo
  };
};


let artist = '',
  album = '';

getAlbumInfo(album, artist)
  .then((res) => {
    const metadata = {
      album: res['album'],
      artist: res['artist'],
      url: res['url']
    };

    return getAlbumArt(metadata);
  })
  .then((o) => {
    console.log(o.res, o.albumInfo);
  })
  .catch(e => {
    console.error(e);
  });

И третьим вариантом будет разрешение второго обещания внутри функции обратного вызова первого обещания:

getAlbumInfo(album, artist)
  .then((res) => {
    const metadata = {
      album: res['album'],
      artist: res['artist'],
      url: res['url']
    };

    getAlbumArt(metadata)
      .then(res2 => {
        // here you can access res, res2 and metadata
      })
      .catch(..);
  })
  .catch(..);
0 голосов
/ 19 февраля 2020

Вы можете использовать его во внутреннем обещании и возвращать любой формат данных, который вам нужен.

getAlbumInfo(album, artist)
.then((res) => {
    const metadata = {
        album: res['album'],
        artist: res['artist'],
        url: res['url']
    };

    return getAlbumArt(metadata).then(responseArt => {
       return {
           innerPromise: responseArt,
           outerPromise: metadata
       };
    });
})
.then((res) => {
    console.log(res);  // Now u have both here

    // I also need the contents of metadata here
})
.catch(e => { console.error(e); });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...