13

How can I get this function to return the value? In all the examples I have seen, folks use an alert in the delegate functions, but I need to return the value instead. When I call the function, it fetches me my default string, which means the executeQueryAsync is not setting the variable.

What am I doing wrong?

var thisuser = SPGetSPcurrentUser();
alert(thisuser);
//-------------------------------------------------------------------
var SPGetSPcurrentUser = function(){
    var spuserid = "Error";
    var context = new SP.ClientContext.get_current();
    this.website = context.get_web();
    this.currentUser = website.get_currentUser();
    context.load(currentUser);
    context.executeQueryAsync(
        function(sender, args){ this.spuserid = currentUser.get_loginName();},
        function(sender, args){ this.spuserid = 'request failed ' + args.get_message() + '\n'+ args.get_stackTrace();}
    )
    return spuserid;
}
bgmCoder
  • 3,581
  • 16
  • 61
  • 102

2 Answers2

15

As the method executeQueryAsync indicates it is asynchronous.
You can actually force the XMLHttpRequest to be synchronous, although that is beside the point.

What you are looking for is a callback function, something like this:

var getSpCurrentUser = function(callback) {
  var ctx = SP.ClientContext.get_current();
  var user = ctx.get_web().get_currentUser();

  ctx.load(user);
  ctx.executeQueryAsync(function() {
    callback(null, user);
  }, function(a, b) {
    callback(new Error(b.get_message()));
  });
};

getSpCurrentUser(function(error, user) {
  if (error) {
    console.error(error);
    return;
  }
  console.log(user.get_title());
});
eirikb
  • 7,405
  • 5
  • 35
  • 67
  • 1
    Thanks, Erik. I've only ever used a callback function once or twice in my life. I don't understand where anything returns the value. Also, could you explain to me how there can be two functions with the same name? (Sorry for being dense) – bgmCoder Dec 07 '12 at 23:36
  • 1
    The value is not returned, instead you pass a function into the getSpCurrentUser as a variable (line 13 and 1, named callback) which will be called from within the getSpCurrentUser function (line 7 and 9). Since executeQueryAsync is asynchronous any code after line 19 will be run before you get your callback (line 14-18). There should not be two functions with the same name – eirikb Dec 07 '12 at 23:48
  • So the first instance of getSpCurrentUser is just a variable, and the second instance, being a callback is really just an extension of the variable? So, to actually call the callback function, I would just use "callback"? – bgmCoder Dec 08 '12 at 01:54
  • I think I don't need the executeQuery to be Async. Is there a way to return the query within the same thread? I realize that would make the script wait. – bgmCoder Dec 08 '12 at 01:55
  • This is the way you are suppose to do it. When dealing with AJAX this is the common approach. You can get around this by augmenting XMLHttpRequest, but that is very bad :) – eirikb Dec 08 '12 at 10:26
  • So, from my original code, where is it that I can get the value into the thisuser variable? I think I am still missing something. – bgmCoder Dec 08 '12 at 17:28
  • I have tried to keep your code as similar as your original one, while also trying to follow some best practices (jshinting), you can see the result here: https://gist.github.com/4241236 – eirikb Dec 08 '12 at 18:26
  • I thank you for that, and I appreciate your time (as well as the "jshinting", honestly I do), but it is necessary that I somehow return the value from SPGetSPcurrentUser. I could get it into an alert using the original code. – bgmCoder Dec 08 '12 at 23:24
  • 1
    With executeQueryAsync it is impossible. I believe you can do it with SPServices. See example – eirikb Dec 09 '12 at 00:44
1

This is the closest I've found to returning a variable reference for the logged-on user.

Try it out it's simple to test: 1. In IE browse to your SharePoint site, open developer tools press (f12) 2. Open the Console press (ctl + 2) 3. Switch line-mode with your cursor in the "Console input" press (ctl + alt + m) 4. Paste all the following contents into the console then press (ctl + enter)

function iWannaDoSomethingWith(thisUser){
 if(thisUser === null){
  alert('failed to get user');
 }
 else{
  alert('User name:' + thisUser.get_title() 
  + '\n Login Name:' + thisUser.get_loginName());
 }
}
function necessaryEvilToWireItAllTogether(nameOfFuncWeReallyWantToCall){
 if (typeof(nameOfFuncWeReallyWantToCall)==="function")
 {
  var ctx = new SP.ClientContext.get_current();
  var oWeb = ctx.get_web();
  var currentUser = oWeb.get_currentUser();
  currentUser.retrieve();
  ctx.load(oWeb);
  ctx.executeQueryAsync(
   function(){
    // successful Async call
    nameOfFuncWeReallyWantToCall(currentUser);
   },
   function(){
    // failed Async call
    nameOfFuncWeReallyWantToCall(null);
   }
  );    
 }
}
ExecuteOrDelayUntilScriptLoaded(function(){necessaryEvilToWireItAllTogether(iWannaDoSomethingWith);}, "sp.js");
SP Combatant
  • 417
  • 2
  • 18