3

私は、GitHub API と連携してユーザー統計を取得する単純な Node.JS アプリを作成しています。/repos/:user/:repo_name/stats/contributorsJSON 文字列を返してくれるGET リクエストを送信しています。これが私の機能です:

function getRepoCommits(token,repos,user,callback) {
    for (var i=0; i<repos.length; i++) {
        var returnChunk = '';
        var full_name = repos[i].full_name;
        //console.log(full_name);
        var options = {
            host: 'api.github.com',
            path: '/repos/'+full_name+'/stats/contributors',
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                'Authorization': 'token '+token,
                'Content-Type': 'application/x-www-form-urlencoded',
            }
        };

        var request = https.request(options, function(res) {
            //res.setEncoding('utf8');
            res.on('data', function(chunk) {
                returnChunk += chunk;
            });
            res.on('end', function(chunk) {
                console.log(returnChunk);
                var stats = JSON.parse(returnChunk);
                console.log(stats.length);
                for (var j=0;j<stats.length;j++) {
                }
                if (i == repos.length-1) {
                    //callback();
                }
            })
        });

        request.on('error',function(err) {
            callback(err);
            console.log(err);
        });
        request.end();
    }
}

関心のある分野はここにあります:

            res.on('end', function(chunk) {
                console.log(returnChunk);
                var stats = JSON.parse(returnChunk);
                console.log(stats.length);
                for (var j=0;j<stats.length;j++) {
                }
                if (i == repos.length-1) {
                    //callback();
                }
            })

の値を確認するとreturnChunk、次の形式の有効な JSON 文字列です。

[{json}]

ただし、関数が に達するJSON.parseと、エラーがスローされます。

SyntaxError:予期しないトークン [

[]基本的に、文字列を解析する前に、文字列の末尾に余分なものを追加しています。あれは。。。になる

[{json}][]

私は何時間もこの問題に対処する方法を見つけようとしましたが、なぜこれを行っているのか理解できないようです. 何かご意見は?

4

1 に答える 1

4

ループ内でいくつかの非同期リクエストを作成し、それらをすべて同じreturnChunk変数に追加しているため、すべてのデータが混ざり合っています。

JavaScript にはブロック スコープがなく、関数スコープしかないためvar returnChunk = ""、関数の先頭に置くようなものです。

解決策は、コールバックが反復ごとに新しいスコープを提供するよう.forEach()に、ステートメントの代わりに使用することです。for

repos.forEach(function(repo, i) {
    var returnChunk = '';
    var full_name = repo.full_name;
    //console.log(full_name);
    var options = {
        host: 'api.github.com',
        path: '/repos/'+full_name+'/stats/contributors',
        method: 'GET',
        headers: {
            'Accept': 'application/json',
            'Authorization': 'token '+token,
            'Content-Type': 'application/x-www-form-urlencoded',
        }
    };

    var request = https.request(options, function(res) {
        //res.setEncoding('utf8');
        res.on('data', function(chunk) {
            returnChunk += chunk;
        });
        res.on('end', function(chunk) {
            console.log(returnChunk);
            var stats = JSON.parse(returnChunk);
            console.log(stats.length);
            for (var j=0;j<stats.length;j++) {
            }

// !!! This will be unreliable because you don't know which one will finish last.
//     You could maintain a separate counter that is incremented as each "end" fires
//        to make sure the `callback()` happens on the last one.
            if (i == repos.length-1) {
                //callback();
            }
        })
    });

    request.on('error',function(err) {
        callback(err);
        console.log(err);
    });
    request.end();
});
于 2013-10-28T01:36:50.153 に答える