I'm using jquery to handle my ajax calls and trying to create small reusable REST calls that can be used individually or chained together. The longer internal workings of the calls are defined down below if that helps. Remember that all of these calls are asynchronous.
I have a function createFolder(title)
which creates a folder in a list and returns the list item id (folderId).
I have a function 'createPermissionGroup(title,members)which creates a permission group and returns the group id. The members argument is optional, if it is defined, then the function calls
addUsersToGroup(groupId,members)`.
All of this is working great by individually.
Now I want to call a function called setFolderPermissions(groupId,folderId,roleDefId)
which needs the groupId returned by createPermissionGroup()
and the folderId returned by createFolder()
.
But for some reason I can't figure out how to get it to wait until both of those functions are completed. I tried the following which I have used in other situations to wait until multiple promises have been resolved, but that resolves immediately. Something is different about this setup and I can't figure it out.
var promises = [];
promises.push(createPermissionGroup(groupName,members))
promises.push(createFolder(groupName))
return $.when($,promises)
I could also chain them like this, but it doesn't seem to be the best/most idiomatic way to do it. And createFolder()
doesn't need the output from createPermissionGroup()
, so I would prefer to start them at the same time and wait until they are both done. It is also kind of hard to read with all the nestings.
var groupId,folderId;
return createPermissionGroup(groupName,members)
.done(function(id){
groupId = id
return createFolder(groupName)
.done(function(id){
folderId =id
return setFolderPermissions(groupId,folderId)
});
});
Anyone have any ideas on how to make this easier to read and more sensible?
Here is the long bit that might help This is my basic ajax and housekeeping stuff.
var listName = 'NameOfList';
var listEntityName = 'SP.Data.NameOfListListItem';
function restCall(obj){
return $.ajax(obj).fail(handleFail);
}
function handleFail(){
console.log('Fail');
}
Then I define some code that will allow me to create a folder in the given list.
function createFolder(title){
var payload = { '__metadata':{'type':listEntityName},
'Title':title,
'FileSystemObjectType':SP.FileSystemObjectType.folder,
'ContentTypeId':"0x0120"
}
var obj = { url: webUrl + "/_api/web/lists/getbytitle('"+listName+"')/Items",
type: "POST",
data: JSON.stringify(payload),
headers:headers.DEFAULT,
}
return restCall(obj)
.then(function(data){
var folderId = data.d.Id;
var title = data.d.Title;
updateFolder(title,folderId)
return(folderId);
})
}
function updateFolder(title,folderId){
// update is required because otherwise the leafref (path) will not
// include the name, it will be "id#_.00" or something like that
var payload = { '__metadata':{'type':listEntityName},
"Title":title,
"FileLeafRef":title
}
var obj = { url: webUrl + "/_api/web/lists/getbyTitle('"+listName+"')/Items("+folderId+")",
type: "POST",
data: JSON.stringify(payload),
headers:headers.PATCH
}
return restCall(obj)
}
This creates the folder and then updates it. This is required because by default the FileLeafRef will get a value like 18._00 which will be confusing later. This way, I can call createFolder('someTitle')
which will return the list item id for the folder. It is also flexible because if I have some other code which already has the item id and a title to update I can just call updateFolder(title,Id)
and it updates.
I also have some code for creating permission groups like this:
function createPermissionGroup(groupName,members){
var payload = { ...item info ...}
var obj = { ...rest info ...}
return restCall(obj)
.then(function(data){
var groupId = data.d.Id
if(typeof members != 'undefined'){
addUsersToGroup(groupId,members);
}
return (groupId);
})
}
function addUsersToGroup(groupId,userArray){
var i, payload, obj;
var promises = [];
var endPoint = webUrl+"/_api/web/SiteGroups("+groupId+")/Users/"
for(i = 0;i<userArray.length;i++){
payload = {...item info}
}
obj = {...rest info...}
promises.push(restCall(obj));
}
return $.when.apply($,promises);
}
.when
, just have to get the syntax right: api.jquery.com/jquery.when Once ES6 is supported theawait
statement will help (but requires a totally different syntax)