# STEW: implementing a Twitter service

Implement a Twitter service to fetch data from Twitter.

The `TwitterService` object that fetches data from Twitter is located in the `TwitterService.js` file. A REST (Representational State Transfer) API call is created by constructing a URL with the appropriate Twitter method name and parameters. The credentials are encoded in the URL to log users into Twitter automatically. A JSON (JavaScript Object Notation) response is requested and the maximum number of returned responses is set. The URL is passed to the `_doRequest` function.

    TwitterService.prototype.getFriendsTweets = function( count, progressId ) {
    	// Build URL and do the request.
    	var url = "http://" + this.username + ":" + this.password + "@twitter.com/statuses/friends_timeline.json?count=" + count;
    	this._doRequest( url );
    }

The `_doRequest` function makes an asynchronous request to the URL. The function also sets the type of the request to GET or POST. Before making the actual request by calling the XMLHttpRequest `send` function a function is assigned to the XMLHttpRequest `readystatechange` event handler.

    TwitterService.prototype._doRequest = function( url, type ){
        this.httpReq = new XMLHttpRequest();

        var self = this;
        this.httpReq.onreadystatechange = function() {
    		self._readyStateChanged();
    	};

    	// Default to GET HTTP request if none is provided.
    	if ( type == null ) {
    		type = "GET";
    	}

        this.httpReq.open( type, url, true );
        this.httpReq.send( "" );
    }

The `_readyStateChanged` function is the heart of the `TwitterService`. The `readystatechange` event is not only triggered when the request is complete so whenever the event handler function gets called, the value of the XMLHttpRequest `readyState` property must be checked. Value 4 (DONE) indicates that the data transfer has been completed or that something went wrong during the transfer. Because it indicates both successful and unsuccessful requests, the response status of the request must be determined by looking at the `status` property of the XMLHttpRequest. If the value is 200 (OK), the response text is retrieved from the XMLHttpRequest `responseText` property. Any other value indicates that an error has occurred during the request.

    TwitterService.prototype._readyStateChanged = function() {
        // complete request?
        if ( this.httpReq.readyState == 4 ) {
            // attempt to get response status
            var responseStatus = null;
            try {
                responseStatus = this.httpReq.status;
            }
    		catch (noStatusException) {
    			alert( StringTable.Code.twitterServiceNoStatusAlert );
    		}

    		// Check response status.
    		if ( responseStatus == 200 ) {
    			var res = null;

    			// If response doesn't contain xml, forward text.
    			res = this.httpReq.responseText;

    			// Not needed anymore.
    			this.httpReq = null;
    			this.handleSuccessResponse.call( this, res );
    		} else {
    			this.handleErrorResponse.call( this, responseStatus );
    		}
        }
    }

Depending on the response status of the request, either `handleSuccessResponse` or `handleErrorResponse` is triggered to notify whoever triggered the request. Since this is all done asynchronously, callback functions are used.

    TwitterService.prototype.handleSuccessResponse = function( arg ) {
    	// Eval the data.
    	var response = eval( "(" + arg  + ")" );

        // Feed fetched and parsed successfully.
    	if ( this.onSuccess )
    		this.onSuccess.call( this, response );
    }

    TwitterService.prototype.handleErrorResponse = function( status ) {
    	if ( this.onError )
    		this.onError.call( this, status );
    }

If `onSuccess` or `onError` functions are defined, they are called with a response object. For an error response, this object is an integer that indicates the status of the request. For a successful response, before triggering the `onSuccess` callback, an `eval` is performed on the response text. This creates JavaScript objects from JSON response text into the response variable, which is then passed as a parameter to the `onSuccess` callback.