尝试使用上一个FM

时间:2019-01-17 18:35:05

标签: arrays json react-native

我对React Native还是很陌生,因为我无法解决的问题而困扰了很长时间。

我解析了带有艺术家和曲目信息的在线JSON文件。网站唯一不提供的是图像URL。因此,我尝试使用lastfm api解析此代码。

我设法从lastfm API获取了URL,但是我不确定除了基本JSON的呈现方式外,如何有效地呈现它。

试图用我需要的东西重新创建对象,但我总是被困在解析它。我总是会得到未定义或功能错误。

在最后一次尝试下(不确定是否是完整尝试)。我尝试了很长时间,所以这可能是一团糟。不要为那哈哈开枪

async initializeNowPlaying () {
await fetch (nowPlayingUrl + showNumberOfTracks)
  .then (response => response.json ())
  .then (responseJson => {
    id = JSON.stringify (responseJson.nowplaying[0].id).replace (/"/g, '');
    title = JSON.stringify (responseJson.nowplaying[0].title).replace (
      /"/g,
      ''
    );
    artist = JSON.stringify (responseJson.nowplaying[0].artist).replace (
      /"/g,
      ''
    );
    dateTime = JSON.stringify (
      responseJson.nowplaying[0].datetime
    ).replace (/"/g, '');
    showName = JSON.stringify (
      responseJson.nowplaying[0].showName
    ).replace (/"/g, '');

    fetch (
      'https://ws.audioscrobbler.com/2.0/?method=track.getInfo&format=json&api_key=my_key&artist=' +
        this.artist +
        '&track=' +
        this.title
    )
      .then (response => response.json ())
      .then (responseJson => {
        if (responseJson !== 'undefined' || responseJson !== '') {
          albumUrl = responseJson.track.album.image[3]['#text'];
        } else {
          albumUrl = 'https://replacedomain.com/logo.png';
        }
      })
      .catch (error => {
        console.log (
          'Geen afbeelding aanwezig. Standaard afbeelding geretourneerd: ' +
            error
        );
        albumUrl = 'https://replacedomain.com/logo.png';
      });
  });
const obj = {
  id: id,
  datetime: dateTime,
  artist: artist,
  title: title,
  albumUrl: albumUrl,
  showName: 'showName',
};

oldObject = this.state.NowPlaying;
newArray = [obj, ...oldObject];
this.setState ({
  NowPlaying: newArray,
});

}

有人可以指出我正确的方向吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

我想我可以看到您正在尝试执行的操作,但是您的代码中存在很多混乱。

您似乎不了解async/awaitpromises之间的区别,本文对https://medium.com/@bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8进行了很好的解释

让我们尝试重构您的代码,以便于阅读和理解。我正在使用async/await,因为它可以使代码更简洁易读,而不是使用promises。这也意味着我不必担心全局变量,也不必尝试从Promise中更新它们,因为某些代码将同步运行,而其他异步运行,这可能会很棘手。使用async/await意味着代码将等待直到await代码完成之后再执行下一行。

  1. 首先删除所有承诺并使用async/await,将所有内容包装在try/catch中,以备等待。
  2. 下载nowPlayingResponse并获取其json。
  3. 获取最终对象所需的所有变量,在访问可能存在或不存在的数组时,您可能希望在此处获得一些保护。
  4. 下载albumResponse并获取其json。
  5. 设置一个默认的albumUrl并对其进行更新(如果可以从json中获取),这可能是更多的保护,而不仅仅是访问对象的一部分。
  6. 最后构造对象并更新状态。
  7. 在捕获中,您应该处理遇到的任何错误。

这是重构

async initializeNowPlaying () {
  try {
    let nowPlayingResponse = await fetch(nowPlayingUrl + showNumberOfTracks);
    let nowPlayingJson = await nowPlayingResponse.json();

    let id = JSON.stringify(nowPlayingJson.nowplaying[0].id).replace(/"/g, '');
    let title = JSON.stringify(nowPlayingJson.nowplaying[0].title).replace(/"/g,'');
    let artist = JSON.stringify(nowPlayingJson.nowplaying[0].artist).replace(/"/g,'');
    let dateTime = JSON.stringify(nowPlayingJson.nowplaying[0].datetime).replace(/"/g, '');
    let showName = JSON.stringify(nowPlayingJson.nowplaying[0].showName).replace(/"/g, '');

    let albumResponse = await fetch (`https://ws.audioscrobbler.com/2.0/?method=track.getInfo&format=json&api_key=my_key&artist=${artist}&track=${title}`);
    let albumJson = await albumResponse.json();

    let albumUrl = 'https://replacedomain.com/logo.png';
    if (albumJson !== 'undefined' || albumJson !== '') {
      albumUrl = responseJson.track.album.image[3]['#text'];
    } 

    const obj = {
      id: id,
      datetime: dateTime,
      artist: artist,
      title: title,
      albumUrl: albumUrl,
      showName: 'showName',
    };

    let oldObject = this.state.NowPlaying;
    let newArray = [obj, ...oldObject];
    this.setState ({ NowPlaying: newArray });
  } catch (err) {
    console.warn(err);
  }
}

很显然,我无法对此进行测试(因为我没有所有的api,键等),因此,这实际上只是一个指南,但是它应该使您对如何使代码正常工作有了一个很好的了解。我想您也将同意,阅读和理解正在发生的事情要容易得多。

下载所有项目

从您的评论看来,您实际上实际上是想下载专辑图像的所有URL并更新播放列表中的项目。您可以使用Promise.all来允许多个请求执行。 虽然执行此操作可能会花费很多时间,但这取决于您要下载的相册数量。您可以在{{3}这里阅读有关使用Promise.all的更多信息。 }

  1. 将用于创建相册对象的代码重构为自己的函数。如果调用成功,它将返回/解析到具有正确相册URL的相册对象,否则返回默认URL。
  2. 使用Promise.all循环遍历nowPlayingJson.nowplaying数组,这将发出每个请求,但是直到所有循环都完成并且每个承诺都已解决,它才能完成。
  3. 将旧的nowPLaying与新的setState相结合来更新setState。

这是新代码:

async initializeNowPlaying () {
  try {
    let nowPlayingResponse = await fetch (nowPlayingUrl + showNumberOfTracks);
    let nowPlayingJson = await nowPlayingResponse.json();

    let newArray = []
    Promise.all(
      nowPlayingJson.nowplaying.map(async album => {
        const albumObj = await getAlbumObject(album)
        newArray.push(albumObj);
      });
    );

    let oldObject = this.state.NowPlaying;
    newArray = [...newArray, ...oldObject];
    this.setState ({ NowPlaying: newArray });
  } catch (err) {
    console.warn(err);
  }
}

async getAlbumObject (album) {
  return new Promise(async (resolve, reject) => {
    let id = JSON.stringify(album.id).replace(/"/g, '');
    let title = JSON.stringify(album.title).replace(/"/g,'');
    let artist = JSON.stringify(album.artist).replace(/"/g,'');
    let dateTime = JSON.stringify(album.datetime).replace(/"/g, '');
    let showName = JSON.stringify(album.showName).replace(/"/g, '');
    let albumUrl = 'https://replacedomain.com/logo.png';

    let obj = { id, title, artist, dateTime, showName, albumUrl };

    try {
      let albumResponse = await fetch (`https://ws.audioscrobbler.com/2.0/?method=track.getInfo&format=json&api_key=my_key&artist=${artist}&track=${title}`);
      let albumJson = await albumResponse.json();
      if (albumJson !== 'undefined' || albumJson !== '') {
        let url = albumJson.track.album.image[3]['#text'];
        if (url) obj.albumUrl = url;
      } 
      resolve(obj);
    } catch (err) {
      resolve(obj);
    }
  })
}

同样,我无法对此进行测试,但是它应该可以使您了解如何执行此操作。