Chained SPService calls give 'Uknown error' and implicit deferred objects must be used?

Dec 4, 2014 at 5:14 PM
Using SPServices to get data from 2 lists, I need 1st answer for the second call:
SPServices{
  ...
  completefunc: {
    ...
    SPServices{
      ...
      completefunc: {
        do something useful with the final result
      }
    }
  }
}
I have decided to use promise chaining instead, so I put deferred.resolve() in completefunc, and it works perfectly:
$(document).ready(function () {
    SP.SOD.executeFunc('sp.js', 'SP.ClientContext', sharePointReady);
});

function sharePointReady() {
    getCurrentUserName().then(getCurrentUserDivisionID).then(getCurrentUserDivisionURL);
}

function getCurrentUserName() {
    var deferred = $.Deferred();
    var context = SP.ClientContext.get_current();
    var web = context.get_web();
    var user = web.get_currentUser();
    context.load(user);
    context.executeQueryAsync(
        function () { //success
            var currentUserName = user.get_title();
            deferred.resolve(currentUserName);
        },
        function (sender, args) { //fail
            deferred.reject();
            console.log("Cannot get current user");
        }
    );
    return deferred.promise();
}

function getCurrentUserDivisionID(currentUserName) {
    var deferred = $.Deferred();
    var mainSiteURL = getMainSiteURL();
    var CAMLViewFieldsListaPracownikow = "<ViewFields>"
        + "<FieldRef Name='ID_division' />"
        + "<FieldRef Name='NameSurname' />"
        + "</ViewFields>";
    var CAMLQueryListaPracownikow = "<Query><Where><Eq>"
        + "<FieldRef Name='NameSurname' />"
        + "<Value Type='User'>" + currentUserName + "</Value>"
        + "</Eq></Where></Query>";
    $().SPServices({
        operation: "GetListItems",
        async: true,
        webURL: mainSiteURL,
        listName: "Workers",
        CAMLQuery: CAMLQueryListaPracownikow,
        CAMLViewFields: CAMLViewFieldsListaPracownikow,
        completefunc: function(xData) {
            var field_divisionID = '';
            $(xData.responseXML).SPFilterNode("z:row").each(function () {
                field_divisionID = $(this).attr("ows_ID_division").split(';')[0];
            });
            if (divisionID === undefined) {
                console.log("Cannot get division ID");
                deferred.reject();
            }
            deferred.resolve(divisionID);
        }
    });
    return deferred.promise();
}

function getCurrentUserDivisionURL(divisionID) {
    var deferred = $.Deferred();
    var mainSiteURL = getMainSiteURL();
    var CAMLViewFieldsStrukturaOrganizacyjna = "<ViewFields>"
            + "<FieldRef Name='divisionURL' />"
            + "<FieldRef Name='ID_division' />"
            + "</ViewFields>";
    var CAMLQueryStrukturaOrganizacyjna = "<Query><Where><Eq>"
        + "<FieldRef Name='ID_division' />"
        + "<Value Type='Integer'>" + divisionID + "</Value>"
        + "</Eq></Where></Query>";
    $().SPServices({
        operation: "GetListItems",
        async: true,
        webURL: mainSiteURL,
        listName: "Divisions",
        CAMLQuery: CAMLQueryStrukturaOrganizacyjna,
        CAMLViewFields: CAMLViewFieldsStrukturaOrganizacyjna,
        completefunc: function(xData) {
            var field_divisionURL;
            $(xData.responseXML).SPFilterNode("z:row").each(function () {
                field_divisionURL = $(this).attr("ows_divisionURL").split(', ')[0];
            });
            if (field_divisionURL === undefined) {
                console.log("Cannot get division URL");
                deferred.reject();
            }
            doSomethingUseful(field_divisionURL); //final function call
            deferred.resolve();
        }
    });
    return deferred.promise();
}

function getMainSiteURL() {
    return window.location.protocol + "//" + window.location.host + _spPageContextInfo.siteServerRelativeUrl;
}
However, SPServices DOES return a promise already! So I am trying to make use of that, but it doesn't work. I am getting 'Unspecified error' inside the activeElement of xData:
$(document).ready(function () {
    var mainSiteURL = getMainSiteURL();
    SP.SOD.executeFunc('sp.js', 'SP.ClientContext', sharePointReady);
});

function sharePointReady() {
    var dID;
    getCurrentUserName().then(getCurrentUserDivisionID).then(function (xData) {
        var field_divisionID = '';
        //_____###!!!###___ xData.activeElement shows 'Unknown error' when I debug using developer console in the browser
        $(xData.responseXML).SPFilterNode("z:row").each(function () {
            field_divisionID = $(this).attr("ows_divisionID").split(';')[0];
        });
        if (field_divisionID === undefined) {
            console.log("Cannot get division ID");
            return;
        }
        return $.when(field_divisionID);
    }).then(getCurrentUserDivisionURL).then(function (xData) {
        var field_divisionURL;
        $(xData.responseXML).SPFilterNode("z:row").each(function () {
            field_divisionURL = $(this).attr("ows_Witryna_x0020_dzia_x0142_u").split(', ')[0];
        });
        if (field_divisionURL === undefined)
            console.log("Cannot get division URL");
            return;
        }
        doSomethingUseful(field_divisionURL); //final function call
    });
}

function getCurrentUserName() {
    var deferred = $.Deferred();
    var context = SP.ClientContext.get_current();
    var web = context.get_web();
    var user = web.get_currentUser();
    context.load(user);
    context.executeQueryAsync(
        function () { //success
            var currentUserName = user.get_title();
            deferred.resolve(currentUserName);
        },
        function (sender, args) { //fail
            deferred.reject();
            console.log("Cannot get current user");
        }
    );
    return deferred.promise();
}

function getCurrentUserDivisionID(currentUserName) {
    var deferred = $.Deferred();
    var mainSiteURL = getMainSiteURL();
    var CAMLViewFieldsListaPracownikow = "<ViewFields>"
        + "<FieldRef Name='ID_division' />"
        + "<FieldRef Name='NameSurname' />"
        + "</ViewFields>";
    var CAMLQueryListaPracownikow = "<Query><Where><Eq>"
        + "<FieldRef Name='NameSurname' />"
        + "<Value Type='User'>" + currentUserName + "</Value>"
        + "</Eq></Where></Query>";
    return $().SPServices({
        operation: "GetListItems",
        async: true,
        webURL: mainSiteURL,
        listName: "Workers",
        CAMLQuery: CAMLQueryListaPracownikow,
        CAMLViewFields: CAMLViewFieldsListaPracownikow
    });
}

function getCurrentUserDivisionURL(divisionID) {
    var deferred = $.Deferred();
    var mainSiteURL = getMainSiteURL();
    var CAMLViewFieldsStrukturaOrganizacyjna = "<ViewFields>"
            + "<FieldRef Name='divisionURL' />"
            + "<FieldRef Name='ID_division' />"
            + "</ViewFields>";
    var CAMLQueryStrukturaOrganizacyjna = "<Query><Where><Eq>"
        + "<FieldRef Name='ID_division' />"
        + "<Value Type='Integer'>" + divisionID + "</Value>"
        + "</Eq></Where></Query>";
    return $().SPServices({
        operation: "GetListItems",
        async: true,
        webURL: mainSiteURL,
        listName: "Divisions",
        CAMLQuery: CAMLQueryStrukturaOrganizacyjna,
        CAMLViewFields: CAMLViewFieldsStrukturaOrganizacyjna
    });
}

function getMainSiteURL() {
    return window.location.protocol + "//" + window.location.host + _spPageContextInfo.siteServerRelativeUrl;
}
Thanks.