I'm writing a tile game in JS and am loading a text based map with a XMLHttpRequest object. All works well until I actually try to draw the background. The map gets initialized, but it doesn't seem to be "fully" initialized by the time I try to loop through the rows. When I try to call map[rowNum].length I get an undefined error. In the debugger, I can see that once the code jumping back to loadMapHttp() which is where the XMLHttpRequest object is defined. I don't understand why it's doing this.
var map =[];
var tiles =[];
var background = new Image();
var canvas = document.getElementById("canvas");
var graphicsContext = canvas.getContext('2d');
background.src = "imgs/tileSheet.jpg";
function loadMapHttp() {
    var conn = new XMLHttpRequest();
    conn.onreadystatechange = handleStateChange;
    conn.open("GET","map.txt",true);
    conn.send();
    function handleStateChange() {
        if(conn.readyState === 4){
            loadMap2(conn.status == 200 ? conn.responseText : null);
        }
    }
}
function loadMap2(text) {
    if(text == null){
        console.warn("Http Error");
        return;
    }
    console.log("text received was: " + text);
    var testMap = text;
    var rows = testMap.split("\n");
    for(var rowNum =0; rowNum < rows.length; rowNum++){
        rows[rowNum] = rows[rowNum].trim();
        map.push([]);
        var cols = rows[rowNum].split("");
        console.log(cols);
        for(var colNum = 0; colNum<cols.length; colNum++){
            map[rowNum][colNum] = cols[colNum];
        }
    }
}
function prepTiles() {
    var TILESET_LEFT = 0;
    var TILESET_TOP = 0;
    var TILE_WIDTH = 31.2;
    var TILE_HEIGHT = 31.2;
    var tileCanvas = document.createElement('canvas');
    var tileContext = tileCanvas.getContext('2d');
    //BRICK
    tileContext.drawImage(background, TILESET_TOP+TILE_WIDTH*2, TILESET_TOP, TILE_WIDTH, TILE_HEIGHT, 0, 0, TILE_WIDTH, TILE_HEIGHT);
    tiles.push(tileContext.getImageData(0, 0, TILE_WIDTH, TILE_HEIGHT));
    //DIRT
    tileContext.drawImage(background, TILESET_LEFT+TILE_WIDTH*17, TILESET_TOP+TILE_HEIGHT*6, TILE_WIDTH, TILE_HEIGHT, 0, 0, TILE_WIDTH, TILE_HEIGHT);
    tiles.push(tileContext.getImageData(0, 0, TILE_WIDTH, TILE_HEIGHT));
    //GRASS
    tileContext.drawImage(background, TILESET_LEFT+TILE_WIDTH*6, TILESET_TOP+TILE_HEIGHT*12, TILE_WIDTH, TILE_HEIGHT, 0, 0, TILE_WIDTH, TILE_HEIGHT);
    tiles.push(tileContext.getImageData(0, 0, TILE_WIDTH, TILE_HEIGHT));
}
function getTile(char) {
    if(char == 'B'){
        return tiles[0];
    }
    if(char == 'D'){
        return tiles[1];
    }
    if(char == 'G'){
        return tiles[2];
    }
}
function drawBackground(){
    for(var rowNum=0; rowNum < 6; rowNum++){
        console.log(map[rowNum]);
        for(var colNum=0; colNum < map[rowNum].length; colNum++){
            var tile = getTile(map[rowNum][colNum]);
            graphicsContext.putImageData(tile, colNum*31, rowNum*31);
        }
    }
}
function startGame() {
    loadMapHttp();
    prepTiles();
    drawBackground();
}
startGame();
