繁体   English   中英

如何从一个 promise 到另一个 promise 获取额外数据?

[英]How can I get additional data from one promise to another?

我有一个承诺依赖于另一个承诺的返回值。 我成功地将该值传递给第二个承诺,但是在第一个承诺中创建了额外的数据,我想以某种方式进入第二个承诺。

这是我的代码:

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 上运行一个获取,它返回第二个承诺。 问题是我需要访问第二个承诺中的专辑元数据。

由于我将元数据返回/传递到第二个承诺中,我尝试在getAlbumArt()使用Object.assign() getAlbumArt()来组合元数据和获取结果,但这似乎不起作用。

有多种方法可以做到这一点,您可以使用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(..);

由于您可以使用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);
  }
})();

希望能帮助到你

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;
};

您可以在内部承诺中使用 then 并在那里返回您想要的任何格式的数据。

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); });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM