2016-07-09 12 views
0

APIの周りに単純なラッパーを構築して、特定のエンティティのすべての結果を取得します。 APIメソッドは一度に最大500件の結果しか返せませんが、結果を取得するインデックスを指定するために使用できるskipパラメータを使用してすべての結果を取得できます。 APIには、合計で存在する結果の数を返すメソッドもあります。API応答を非同期的に正しい順序で連結する

requestパッケージを使用して時間を費やして、すべての結果を順番に連結し、すべての結果を通過させるコールバックを実行しています。

これは、現在、私のコードです:

Donedone.prototype.getAllActiveIssues = function(callback){ 
    var url = this.url; 
    request(url + `/issues/all_active.json?take=500`, function (error, response, body) { 
     if (!error && response.statusCode == 200) { 
      var data = JSON.parse(body); 
      var totalIssues = data.total_issues; 
      var issues = []; 
      for (let i=0; i < totalIssues; i+=500){ 
       request(url + `/issues/all_active.json?skip=${i}&take=500`, function (error, response, body){ 
        if (!error && response.statusCode == 200) { 
         console.log(JSON.parse(body).issues.length); 
         issues.concat(JSON.parse(body).issues); 
         console.log(issues); // returns [] on all occasions 
         //callback(issues); 
        } else{ 
         console.log("AGHR"); 
        } 
       }); 
      } 
     } else { 
      console.log("ERROR IN GET ALL ACTIVE ISSUES"); 
     } 
    }); 
}; 

は、だから私は空の配列、issuesでオフ始めています。 forループを繰り返し、毎回iを500ずつ増やして、それをskip paramとして渡します。ご覧のとおり、各応答にメインのissues変数を連結する前に、各応答に含まれる問題の長さを記録しています。 869の結果の合計から

出力は、このです:私はそれをログアウトするとき

369 
[] 
500 
[] 

なぜ私の問題は、空の変数のですか?それを連結する明確な結果があります。

もっと一般的な質問:私が達成しようとしていることについては、このアプローチが最善の方法ですか?私は自分のコードが機能したとしても、非同期の性質は結果が間違った順序で連結される可能性があることを意味していました。

同期要求ライブラリを使用するだけでいいですか?

答えて

1

ログアウトする際に、問題の変数が空白なのはなぜですか?明らかにそれを連結するために の結果があります。

ここでの主な問題は、.concat()が新しい配列を返すことです。既存の配列に項目を追加することはありません。

あなたは、これを変更することができます。これに

issues.concat(JSON.parse(body).issues); 

を:

issues = issues.concat(JSON.parse(body).issues); 

は、新しい連結配列を保持していることを確認します。これは非常に一般的な間違いです。あなたがまたは背面の適切な順序で到着しない可能性があり、同じ時間と結果の要求の全体の束を開始しているforループを実行しているので、


また、潜在的にあなたの配列内のシーケンスの問題を持っています。あなたはまだ問題の適切な総数を取得しますが、要求された順序ではない可能性があります。それがあなたにとって問題であるかどうかは分かりません。それが問題であれば、それについての修正を提案することもできます。

より一般的な質問:このアプローチは、私が達成しようとしているものについては に行くのが最も良い方法ですか?私のコードがうまくいっても、 の性質は、 の結果が間違った順序で連結される可能性があることを意味します。

問題を修正することもできますが、これは妥当な方法です。これがAPIを使用して結果を得る最も効率的な方法であるかどうかを知るためには、APIについてもっと知る必要があります。通常、同じサーバーへのN回の繰り返しのAPI呼び出しを避けたいのであれば、すべての結果を得るために1回のAPI呼び出しを行います。

同期要求ライブラリのみを使用する必要がありますか?

絶対にありません。 node.jsには、非同期プログラミングを行う方法を学習する必要があります。これはほとんどの人にとって学ぶステップですが、node.jsからどのように最高のパフォーマンスを引き出すかを学び、使用する必要があります。

// promisify the request() function so it returns a promise 
// whose fulfilled value is the request result 
function requestP(url) { 
    return new Promise(function(resolve, reject) { 
     request(url, function(err, response, body) { 
      if (err || response.statusCode !== 200) { 
       reject({err: err, response: response}); 
      } else { 
       resolve({response: response, body: body}); 
      } 
     }); 
    }); 
} 

Donedone.prototype.getAllActiveIssues = function() { 
    var url = this.url; 
    return requestP(url + `/issues/all_active.json?take=500`).then(function(results) { 
     var data = JSON.parse(results.body); 
     var totalIssues = data.total_issues; 
     var promises = []; 
     for (let i = 0; i < totalIssues; i+= 500) { 
      promises.push(requestP(url + `/issues/all_active.json?skip=${i}&take=500`).then(function(results) { 
       return JSON.parse(results.body).issues;     
      })); 
     } 
     return Promise.all(promises).then(function(results) { 
      // results is an array of each chunk (which is itself an array) so we have an array of arrays 
      // now concat all results in order 
      return Array.prototype.concat.apply([], results); 
     }) 
    }); 
} 

xxx.getAllActiveIssues().then(function(issues) { 
    // process issues here 
}, function(err) { 
    // process error here 
}) 
+0

ああ、私の愚かな:ここで


は(非同期Node.jsの中に処理するために非常に有用である)、同期、エラー伝播のための約束を使用して信頼性のために、すべての結果を収集するための方法です連結。約束を使って本当に面白い解決策!前にそれらを使用していない、それはスピン、感謝を与えるだろう。 – Jazcash

+1

@ Jazcash - この特定のケースの約束について本当にうれしいことは、リクエストを並行して実行しても、Promise.all()が順番に結果を収集することです。また、エラー処理の方がはるかに優れています。これは、(返された約束によって)呼び出し元に戻ります。これは、要求ループのどこかで発生するエラーです。コードでエラーが返されませんでした。 – jfriend00

関連する問題