user3258341
user3258341

Reputation: 21

Javascript Asynchronous Issue (Sharepoint)

Hopefully somebody can show me a way to do this, and explain why this code is failing. I believe it is a scope issue but have banging my head on it for a few days.

Let me first explain what the code is doing. I have a HTML button on a web part aspx page that runs a function in a js file. The code searches my Sharepoint list for items that are missing two field values, via a CAML query. It then loops through the items, and calls an asynchronous web service for each item. The asynchronous event returns a promise, that I use the ,to update each of the items with the 2 values retuned by the asynchronous event. Each item is then saved back to the server, which is where my issue is occurring. When I debug this, the Function.createDelegate(this, this.success) has an udefined argument (b), that blows up on b.apply(). This is definitely not my strong suit in javascript. Can somebody help? See Code below:

Note - See //*Save Comment in Asychronous Function section for line which is causing issues.

HTML Button Calls Function

function UpdateSegmentSubsegment()
{
    //1.) Query items where segment & sub-segment blank returnin array of items *
    //2.) Loop through retuned items *
    //3.) Get employee id *
    //4.) Call Web Service and return segment & subsegment for employee id
    //5.) Update item with segment & subsegment + Save
    //6.)Loop

    //Query Information Variables
    var listname='ERD - XXXXX';
    var caml='<View Scope="Recursive"><Query><Where><And>' +
    '<IsNull><FieldRef Name="Employee_x0020_Business_x0020_Se"  /></IsNull>' + 
    '<IsNull><FieldRef Name="Employee_x0020_Business_x0020_Su"  /></IsNull>' + 
    '</And></Where></Query></View>';

    //Function Variables
    var itemcount=0;
    var context = new SP.ClientContext.get_current();

    QueryListItems(listname,caml,context).then(function(items){
        //Get item count returned from promise
        itemcount=items.get_count();
        window.status="Preparing to Process"+itemcount.toString()+" items..."

        //Prepare Looping object
        var listitemenumerator=items.getEnumerator();

        //Loop through each List Item
        while (listitemenumerator.moveNext()) {
            //Get Employee ID from list item collection
            var listitem = listitemenumerator.get_current();
            var employeeid=listitem.get_item("EmpUseAcct");

            //Check for invalid item value
            if(employeeid!="#Value!"){
                //Ansychronous Function Call
                QueryHRInformation(employeeid,listitem,context);
            }
            else
            {
                //Log CA Skip
                window.status="Skiping CA Number "+listitem.get_item("Title").toString();
            }
        };


    }); 
}

Query Function

//Query Promise
function QueryListItems(listname, CAMLQ,clientContext)
{
    //Defererred Object
    var deferred = new $.Deferred();

    //Sharepoint Object Model

    //Get List
    var list = clientContext.get_web().get_lists().getByTitle(listname);

    //CAML Query
    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml(CAMLQ);        
    var items = list.getItems(camlQuery);

    //Get Items
    clientContext.load(items);
        clientContext.executeQueryAsync(
        Function.createDelegate(this,
            function () { deferred.resolve(items); }),
        Function.createDelegate(this,
            function (sender, args) { deferred.reject(sender, args); }));

    return deferred.promise();
}

Asychronous Function

//Asnchronous Function Call
function QueryHRInformation(employeeid,listitem,clientContext){
    //Web Service Variables
    var curequestorID="XXXXXX";
    var wsserviceID="someweb-serviceid";
    var wsservicePassword="somepassword";
    var appIdentifier="someid";
    var wsserviceName="SomeDetails";

    //Debugging Variable to check async list item object
    var title;

    //Asynchronous Call
    XXX.ERD.BizTalk.XX.getInstance().getInfo(employeeid,curequestorID, wsserviceID, wsservicePassword, appIdentifier, wsserviceName).then(function(empResult){

            //Debugging Check
            title=listitem.get_item("Title");

            //Set list item values from web service object return (empResult)
            listitem.set_item("Employee Business Segment",empResult.BusSegment);
            listitem.set_item("Employee Business Sub Segment",empResult.SubSegment);
            //Update list item values
            listitem.update();

            //*Save Item
            clientContext.executeQueryAsync(Function.createDelegate(this, this.success), Function.createDelegate(this, this.failed));**

    }); 
}

Upvotes: 0

Views: 735

Answers (2)

user3258341
user3258341

Reputation: 21

Well I never leave my questions unanswered so others in the development community may benefit from my questions. Too many posts go unanswered, or just end after a solution is reached.

Yes, I figured it to be scoping issue a few weeks back, and solved my own issue. I wrapped them into functions passing along the values. When it is sent to the stack, it will not lose the scope of the values from the previous asynchronous call.

Inside the first function that makes an asynchrounous I pass the values and call this function:

SaveItem(listitem, clientContext, businesssegment,subsegment);

Here is the complete code:

function UpdateSegmentSubsegment()
{
    //Prompt for Batching Note: Leave it blank to do all.
    var camlrowlimit=prompt("Please enter the batch query","");
    var camlbatch;

    //Check Batch Input
    if(camlrowlimit!=null)
    {
        //Set Dynamic RowLimit Variable 
        if(camlrowlimit=="")
        {
            camlbatch="";
        }
        else
        {
            camlbatch="<RowLimit>"+camlrowlimit+"</RowLimit>";
        }

        //Query Information Variables
        var listname='ERD - XXXXX';
        var caml='<View Scope="Recursive"><Query><Where><And>' +
        '<IsNull><FieldRef Name="Employee_x0020_Business_x0020_Se"  /></IsNull>' + 
        '<IsNull><FieldRef Name="Employee_x0020_Business_x0020_Su"  /></IsNull>' + 
        '</And></Where></Query>'+camlbatch+'</View>';

        //Function Variables
        var itemcount=0;
        var context = new SP.ClientContext.get_current();

        QueryListItems(listname,caml,context).then(function(items){
            //Get item count returned from promise
            itemcount=items.get_count();
            window.status="Preparing to Process "+itemcount.toString()+" items..."

            //Prepare Looping object
            var listitemenumerator=items.getEnumerator();

            //Loop through each List Item
            while (listitemenumerator.moveNext()) {
                //Get Employee ID from list item collection
                var listitem = listitemenumerator.get_current();
                var employeeid=listitem.get_item("EmpUseAcct");

                //Check for invalid item value
                if(employeeid!="#Value!"){
                    //Ansychronous Function Call
                    QueryHRInformation(employeeid,listitem,context);
                }
                else
                {
                    //Log CA Skip
                    console.log("Skiping CA Number "+listitem.get_item("CorrectiveActionNumber"));
                }
            };


        }); 
    }
}


//Query Promise
function QueryListItems(listname, CAMLQ,clientContext)
{
    //Defererred Object
    var deferred = new $.Deferred();

    //Sharepoint Object Model

    //Get List
    var list = clientContext.get_web().get_lists().getByTitle(listname);

    //CAML Query
    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml(CAMLQ);        
    var items = list.getItems(camlQuery);

    //Get Items
    clientContext.load(items);
        clientContext.executeQueryAsync(
        Function.createDelegate(this,
            function () { deferred.resolve(items); }),
        Function.createDelegate(this,
            function (sender, args) { deferred.reject(sender, args); }));

    return deferred.promise();
}

//Asnchronous Function Call
function QueryHRInformation(employeeid,listitem,clientContext){
    //Web Service Variables
    var curequestorID="XXXXXX";
    var wsserviceID="XXXXXX";
    var wsservicePassword="XXXXXX";
    var appIdentifier="XXXXXX";
    var wsserviceName="XXXXXXX";

    //Debugging Variable to check async list item object
    //var title;

    //Asynchronous Call
    XXX.ERD.BizTalk.XX.getInstance().getInfo(employeeid,curequestorID, wsserviceID, wsservicePassword, appIdentifier, wsserviceName).then(function(empResult){

            //Empresult.status
            var businesssegment=empResult.BusSegment;
            var subsegment= empResult.SubSegment;
            SaveItem(listitem, clientContext, businesssegment,subsegment);          

            //*Save Item

            //clientContext.executeQueryAsync(Function.createDelegate(this, this.success), Function.createDelegate(this, this.failed));

    })
    .fail(function(xhr, status, msg){
                    console.log(msg);
    });                                         
}

function SaveItem(item,ctx,bsg,ssg)
{
    var refno;

    //Debugging Check
    refno=item.get_item("CorrectiveActionNumber");  
    //Set Fields
    item.set_item("Employee_x0020_Business_x0020_Se",bsg);
    item.set_item("Employee_x0020_Business_x0020_Su",ssg);
    //Update list item values
    item.update();
    //ctx.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded),Function.createDelegate(this, this.onQueryFailed));
    ctx.executeQueryAsync(Function.createDelegate(this,function(){ onQuerySucceeded(refno);}),Function.createDelegate(this, this.onQueryFailed));

}

function onQuerySucceeded(result, args) {
    console.log('Saved CA Number'+result); 
}

function onQueryFailed(sender, args) {
    console.log('Request failed. ' + args.get_message()+'\n' + args.get_stackTrace());

}

Upvotes: 1

user9035386
user9035386

Reputation:

This should really be a comment but since do not have enough 'reputation'...

Anyway, to check whether it is a scoping issue, replace the issue line with this:

clientContext.executeQueryAsync(function(){console.log("Success"},function(){console.log("failed"})

If this resolves the issue then it was some sort of scoping issue.

Also, see this link for the correct syntax for updating item (i.e try to declare client context etc again when updating): https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/complete-basic-operations-using-javascript-library-code-in-sharepoint#create-update-and-delete-list-items

Finally, I recommend using this library: https://aymkdn.github.io/SharepointPlus/

Upvotes: 0

Related Questions