Search code examples
javascriptjquerypromisespservices

Returning Object from a Promise


I'm a bit new to using promises and am having an issue returning an object. I have the following function that calls SPServices to retrieve one item from a list. I know the SPService call is returning the list item, but the data returning is undefined:

$('.support-View').on('click', function () {
    var thisID = $(this).data("id");
    var message = getOneDetails(thisID);
    console.log("This Data  : " + message); //<-- Comes back undefined
    $.when(message).done(function() {
        thisMessage = message;
        viewRequestDialog(thisID, message);
    });
});

And the getOneDetails function looks like this:

function getOneDetails (thisID, viewtype) {

var CAML = '<Query><Where><Eq><FieldRef Name="Title" /><Value Type="Text">' + thisID + '</Value></Eq></Where></Query>';
var list = 'Support Requests';

var requestsPromise = $().SPServices.SPGetListItemsJson({
    listName: list,
    CAMLQuery: CAML,
    includeAllAttrs: true
});

$.when(requestsPromise).done(function() {
    requestData = this.data;
    console.log(this.data); //<---- Data is defined here

    })
    .then(function(requestData) {
    console.log(requestData); //<---- But undefined here
    return requestData;
}); 

}

Im sure I'm missing something simple, but how do I simply return the object from the promise function? TIA


Solution

  • You never can return a value from a promise, because it might not yet have arrived. You only can return another promise, for a value that is computed from the result of the first promise. Your first snippet needs to look like this:

    $('.support-View').on('click', function () {
        var thisID = $(this).data("id");
        var messagePromise = getOneDetails(thisID);
        messagePromise.done(function(message) {
            console.log("This Data  : " + message); // <-- Comes back as an argument
                                                    //     to the callback
            // thisMessage = message; // Don't ever do this. Global variables are
                                      // useless when you don't know *when* they
                                      // will contain a value. If you need to store
                                      // something, store the `messagePromise`.
            viewRequestDialog(thisID, message);
        });
    });
    

    Your getOneDetails function needs to return a promise, it currently doesn't return anything. Why this.data is defined, but not passed as an argument to the callback I'm unsure; yet even when you did assign that to a global requestData variable that value will be shadowed by the local requestData variable (named parameter) of the then callback.

    Ideally, it should look

    return requestsPromise.then(function(requestData) { /*
    ^^^^^^ notice the return! */
        console.log(requestData); // <---- Data is given as an argument
        return requestData;
    });
    

    but you might need to do

    return requestsPromise.then(function() { // again, return the result of the call
        var requestData = this.data; // take it from wherever (unsure what `this` is)
    //  ^^^ local variable
        console.log(requestData); // <-- Data is defined here
        return requestData; // and can be returned to resolve the promise with
    });