2016-10-01 23 views
1

私は現在Spotify APIから約束したデータを取得しようとしていますが、昨日は同じトピックに関する別の質問について大きな助けを得ました: "Loop the object returned from node promise and feed to the next .then"ノードの約束からのデータ返信

私がしていることは、まず自分のプレイリストからトラックを取得してから、アーティストを取得する別のAPIを呼び出します。最後に、アーティストの画像を取得する別のAPIを呼び出します。 私の質問は、私が約束したデータをどのように返すのですか?

これは、プレイリストのURLを取得する私の関数である。

function getPlaylists(access_token) { 

    var options = { 
     url: 'https://api.spotify.com/v1/me/playlists', 
     headers: { 'Authorization': 'Bearer ' + access_token }, 
     json: true 
    }; 

    return new Promise(function(resolve, reject) { 

     request.get(options, function(error, response, body) { 
     var playlists = body.items; 
     var playlistArray = []; 
     playlists.forEach(function(playlist) { 
      var name = playlist.name; 
      var url = playlist.tracks.href; 

      playlistArray.push(url); 
     }); 

     if(!error) { 
      resolve(playlistArray); 
     } else { 
      reject(error); 
     } 

    }); 

    }); 
} 

この1つは、アーティストを取得:

function getArtists(url,access_token) { 

    var params = { 
    url: url, 
    headers: { 'Authorization': 'Bearer ' + access_token }, 
    json: true 
    }; 

    return new Promise(function(resolve, reject) { 

    request.get(params, function(error, response, body) { 

     var tracks = body.items; 
     var artistArray = []; 
     tracks.forEach(function(artists) { 
      let allArtists = artists.track.artists; 
      allArtists.forEach(function(artist) { 
       artistArray.push(artist); 
      }); 
     }) 

     if(!error) { 
      resolve(artistArray); 
     } else { 
      reject(error); 
     } 

    }); 

    }) 

} 

をそして、この1は、アーティスト画像取得:

function getArtistImages(artistId) { 
    var options = { 
     url: 'https://api.spotify.com/v1/artists/' + artistId, 
     json: true 
    }; 

    return new Promise(function(resolve, reject) { 
     request.get(options, function(error, response, body) { 
      if(error != null) { 
       reject(error); 
      } else { 
       resolve(body); 
      } 
     }); 
    }) 

} 

をEDIT EDIT 私はカールリットルこれらの関数は、このようなものです: - それは唯一の前に、一度foreachループをループになっているため「(res.send)」は明らかなので、どのように私はそれを確認してください

getPlaylists(access_token) 
     .then(playlists => Promise.all(playlists.map(playlist => 
     getArtists(playlist, access_token))) 
     .then(artists => { 

     artists.map(artist => { 
      artist.map(a => { 
      console.log(a); 
      let component = renderToString(
       <App> 
        <Table artists={a} /> 
       </App> 
      ); 

      res.send(
       component 
      ) 
      }) 


     }) 

     })); 

それだけで最初の結果を返します。ビューをレンダリングする前に、すべてのアーティストをループしますか?私は別のPromise.all()をやらなければならないと信じていますが、誰が考えを持っているのかは分かりません。

私はそれを感謝:)

+0

あなたの質問の解決策が何であるかはまだ分かりませんでしたが、私が今言うことができるのは、 'artist.map()'関数の中に何も返さないということです。また、 'array.push(obj [key])'に 'key 'が何か見えませんでした。 –

+0

はい、変数キーをテストから削除するのを忘れました。私は別のプロミスをやらなければならないと信じています。 –

+0

データとその構造について説明できますか?あなたのコードで伝えるのはとても混乱しているからです。 'getArtists'は' * '(Promise of)配列の配列を返しますが、 'getArtistImages'は' img'を返します。 *(オプション)* images配列には実際の画像が含まれています – Thomas

答えて

0

私が正しくあなたの問題を理解していれば、あなたが実際にPromisesの結果を使用する方法にまでトリップしているように、それが聞こえます。

非同期アプリケーション:

Promisesthen()に渡されるコールバックを介して利用可能にされる非同期結果をカプセル化。

このasynchronous-ismは、アプリケーション全体でカスケードします。

方法アプリケーションの数がありますが、非同期の結果の現実を管理する:イベント、コールバック、観測、約束...(イベントを使用して)

例:これは、粗

をし、非同期リクエストからのデータがビューにどのように注入されるかについての、未テストの例です。私の非同期要求が私のthen()コールバックを呼び出すと、ビューを再レンダリングするイベントをトリガーするモデルを更新します。

私の全体のビューを再レンダリングしたくない場合、getArtists()が私のビューがロード状態をレンダリングできるよりも早く戻る場合はどうしたらよいでしょうか?しかし、わかりやすくするために、私たちはそこに行かないでしょう。

+function(){ 


    var _view = $('#viewport'); 
    var _model = {...} 
    var _spotifyClient = new SpotifyClient(); // this contains method similar to those you included in your question 

    _view.on('load', onLoad); 
    _view.on('model:update', onModelUpdate); 

    function onLoad() { 
     _spotifyClient 
     .getArtists() 
     .then(function(result) { 
      // when the getArtists() request has responded, I can update my model. 
      updateModel({ isLoading: false, artists: result }); 
     })   

     // this will happen immediately after starting the "getArtists()" request. 
     udpateModel({ isLoading: true }); 
    } 

    function updateModel(mod) { 
     for(var p in mod) { 
      _model[p] = mod[p]; 
     } 
     _view.trigger('model:update', _model); 
    }   

    function onModelUpdate(model) { 
     refreshView(); 
    } 

    function refreshView() { 
     var viewModel = buildTemplateModel(_model); 
     renderTemplate(_view, viewModel); 
    } 

}(); 

角度、ノックアウト、反応などのいくつかのビューフレームワークを研究することをお勧めします。Reactive Extensionsを調べて、観測可能なインターフェイスと非同期ストリームに関する多くのユーティリティを提供することをお勧めします。副作用の

注:

イベントは、「副作用」として分類することができます約束トリガーの結果を持ちます。アプリケーションでは副作用を最小限に抑える必要があり、実際にはアプリケーションのコントローラ/メイン部分にのみ属します。

アプリケーションで約束を使用している場合、約束しているライブラリクラスと関数を再利用すると、約束が返されます。

+0

はい、私は本当に約束のまわりで私の頭を包んでいない、私は推測する:)新しい編集を確認してください、私はほとんどそこにいると思う。 –

0

あなたがいない個別1に、すべての結果の配列にres.sendを呼び出す必要があります:

getPlaylists(access_token).then(playlists => 
    Promise.all(playlists.map(playlist => 
     getArtists(playlist, access_token) 
    )) 
).then(artists => { 
    res.send(artists.map(artist => 
     artist.map(a => { 
      console.log(a); 
      return renderToString(
       <App> 
        <Table artists={a} /> 
       </App> 
      ); 
     }) 
    )) 
}); 

また、あなたの括弧は、わずかに(then呼び出しのインデントと一致しませんでした)それのdidnをmisnestedました問題につながることはありません。

+0

こんにちは、hm、それはHTMLの配列を返します。 –

+0

ええ、それはあなたが望んでいたものではありませんか? – Bergi

+0

すべての結果の配列を返すと言ったことを正確に欲しがります。しかし、これはページ全体の配列を返します。このように: "

0

古い投稿ですが、それは誰かのために役立つと思います。

私は、並行性をサポートする約束事に基づいてforeachを実行するプラグインを作成しました。私はあなたが他のソリューションを適用するためにより簡単なものを回す並行性が必要ないと思う。

私のプラグインを使用してコードでコードを書きました。できます!

'use strict'; 

var request = require('request') 
var promiseForeach = require('promise-foreach') 

function getPlaylists(access_token) { 

    var options = { 
     url: 'https://api.spotify.com/v1/me/playlists', 
     headers: { 'Authorization': 'Bearer ' + access_token }, 
     json: true 
    }; 

    return new Promise(function (resolve, reject) { 

     request.get(options, function (error, response, body) { 
      var playlists = body.items; 
      var playlistArray = []; 
      playlists.forEach(function (playlist) { 
       var name = playlist.name; 
       var url = playlist.tracks.href; 
       playlistArray.push(url); 
      }); 
      if (!error) { 
       resolve(playlistArray); 
      } else { 
       reject(error); 
      } 
     }); 

    }); 
} 

function getArtists(url, access_token) { 

    var params = { 
     url: url, 
     headers: { 'Authorization': 'Bearer ' + access_token }, 
     json: true 
    }; 

    return new Promise(function (resolve, reject) { 

     request.get(params, function (error, response, body) { 

      var tracks = body.items; 
      var artistArray = []; 
      tracks.forEach(function (artists) { 
       let allArtists = artists.track.artists; 
       allArtists.forEach(function (artist) { 
        artistArray.push(artist); 
       }); 
      }) 

      if (!error) { 

       promiseForeach.each(artistArray, 
        [function (artist) { 
         return getArtistImages(artist.id) 
        }], 
        function (arrayOfResultOfTask, currentList) { 
         return { 
          artistId: currentList.id, 
          artistName: currentList.name, 
          artistImages: arrayOfResultOfTask[0].images 
         } 
        }, 
        function (err, newList) { 
         if (err) { 
          console.error(err) 
          return; 
         } 
         resolve(newList) 
        }) 

      } else { 
       reject(error); 
      } 

     }); 

    }) 

} 

function getArtistImages(artistId) { 
    var options = { 
     url: 'https://api.spotify.com/v1/artists/' + artistId, 
     headers: { 'Authorization': 'Bearer ' + access_token }, 
     json: true 
    }; 

    return new Promise(function (resolve, reject) { 
     request.get(options, function (error, response, body) { 
      if (error != null) { 
       reject(error); 
      } else { 
       resolve(body); 
      } 
     }); 
    }) 

} 

var access_token = 'YOUR-TOKEN'; 


getPlaylists(access_token) 
    .then(playlists => { 

     promiseForeach.each(playlists, 
      [function (playlist) { 
       return getArtists(playlist, access_token) 
      }], 
      function (arrayOfResultOfTask, currentList) { 
       return { 
        playlistURL: currentList, 
        artist: arrayOfResultOfTask[0] 
       } 
       //return renderToString(
       // <App> 
       //  <Table artists={render} /> 
       // </App> 
       //); 
      }, 
      function (err, newList) { 
       if (err) { 
        console.error(err) 
        return; 
       } 
       res.send(newList) 
      }) 

    }); 

プラグイン:https://www.npmjs.com/package/promise-foreach

私はそれが誰かを役に立てば幸い!