google URL shortener,等待数据被完全接收 - NodeJS

时间:2014-03-21 10:09:07

标签: javascript json node.js

我正在尝试使用Google的网址缩短API。 我正在使用此代码使用节点JS缩短它:

function _shorten (url, callback) {
    if (!url) { 
        console.error('Please specify a valid url.');
        return; 
    }

    if (typeof _url.parse(url).protocol === 'undefined') {
        url = 'http://' + url;
    }

    if (!callback) { callback = false; }

    var key = _getKey(),
        options = {
            host: 'www.googleapis.com',
            port: 443,
            path: '/urlshortener/v1/url' + (key ? '?' + _querystring.stringify({'key': key}) : ''),
            method: 'POST',
            headers: {
                'content-type': 'application/json'
            }
        };

    var req = _https.request(options, function(res) {
        res.setEncoding('utf8');
        res.on('data', function (d) {
            d = JSON.parse(d); // <--- here is the problem
            if (callback) {
                callback(d);
            } else {
                console.log(d.id || d.error);
            }
        });
    });

    req.on('error', function(e) { console.error(e); });

    req.write(JSON.stringify({'longUrl': url}));

    req.end();
}

但是,当我尝试使用基本URL运行它时,我收到以下错误:

undefined:1
{
 ^
SyntaxError: Unexpected end of input
    at Object.parse (native)
    at IncomingMessage.<anonymous> (/Users/PATH/node_modules/goo.gl/lib/googl.js:45:26)
    at IncomingMessage.EventEmitter.emit (events.js:95:17)
    at IncomingMessage.<anonymous> (_stream_readable.js:746:14)
    at IncomingMessage.EventEmitter.emit (events.js:92:17)
    at emitReadable_ (_stream_readable.js:408:10)
    at emitReadable (_stream_readable.js:404:5)
    at readableAddChunk (_stream_readable.js:165:9)
    at IncomingMessage.Readable.push (_stream_readable.js:127:10)
    at HTTPParser.parserOnBody [as onBody] (http.js:142:22)

我相信这是因为我在完全收到数据之前试图解析收到的数据。当我删除d = JSON.parse(d);我的回调被多次调用,我得到以下结果:

{



"
k
i
n
d
"
:

"
u
r
l
s
hortener#url",
 "id": "http://goo.gl/test",
 "longUrl": "http://test.com"
}

我该如何解决这个问题?我应该做这样的事情,因为我只对'id'字段感兴趣吗?:

    if d contains 'id' then 
     d = JSON.parse(d);
            if (callback) {
                callback(d);
            } else {
                console.log(d.id || d.error);
            }

感谢

2 个答案:

答案 0 :(得分:0)

您需要累积数据直到完成,然后执行JSON.parse()。因此,您要继续在.on('data',...)事件处理程序中扩充数据,并且需要在JSON.parse()事件处理程序中传输callback.on('end',...)存在检查。

来自http.ClientRequest上的Nodejs文档:

However, if you add a 'response' event handler, then you must consume the data from the
response object, either by calling response.read() whenever there is a 'readable' event,
or by adding a 'data' handler, or by calling the .resume() method. Until the data is
consumed, the 'end' event will not fire. Also, until the data is read it will consume
memory that can eventually lead to a 'process out of memory' error.

答案 1 :(得分:0)

好的,我设法解决了这个问题:

    var req = _https.request(options, function(res) {
        var message = "";
        var id = "id";
        res.setEncoding('utf8');
        res.on('data', function (d) {
            message += d;

            var idIndex = message.indexOf(id);
            var didFindId = idIndex != -1;
               if (didFindId) {
                    if (callback) {
                        message = JSON.parse(message);
                        callback(message);   
                    } else {
                        console.log(d.id || d.error);
                    }
                }
        });
    });

我检查我的数据是否包含&#34; id&#34;累积到目前为止收到的所有数据后,我才发送