Please disregard. Instead of appending each row to the table during the loop, I created a varable outside of the getListItems call and appended to its value. Once getListItems was done I appended this variable to the table.
$(document).ready(function(){
getListItemsGeneric("https://site", "first column text", "my library name");
function getListItemsGeneric(listUrl, firstColumn, listName){
var thisUrl = listUrl;
var thisFirstColumn = firstColumn;
var thisListName = listName;
var buildHTML; //new variable to build html
$().SPServices({
operation: "GetListItems",
webURL: thisUrl,
async: false,
listName: thisListName,
completefunc: function (xData, Status) {
//alert("Status of XML message reaching Sharepoint webservice: " + Status);
//alert("Response from server: " + xData.responseXML.xml);
$(xData.responseXML).find("[nodeName=z:row]").each(function() {
//find the title. use filename if title is not populated
strTitleField = $(this).attr("ows_Title");
if(!strTitleField){
strTitleField = $(this).attr("ows_LinkFilename");
}
strDocumentLink = $(this).attr("ows_FileRef");
strDocumentLink = "https://myserver/" + strDocumentLink.substring(strDocumentLink.indexOf(';#')+2, strDocumentLink.length);
strCat1 = $(this).attr("ows_Category_x0020_1");
if(!strCat1) {
strCat1 = '';
}
strCat2 = $(this).attr("ows_Category_x0020_2");
if(!strCat2) {
strCat2 = '';
}
var Html = "<tr>";
Html += "<td>zzzzzzzzzz</td>";
Html += "<td><a href='" + strDocumentLink + "' target='_blank'>" + strTitleField.replace(/_/g,' ') + "</a></td>";
Html += "<td>" + strCat1 + "</td>";
Html += "<td>" + strCat2.substring(0,30) + "</td>";
Html += "</tr>";
//append html to function variable
buildHTML += Html;
});
}
});
buildHTML = buildHTML.replace(/zzzzzzzzzz/g, thisFirstColumn);
$('#tableid').find('tbody').append(buildHTML);
}
});