I have a scenario of fetching data from multiple SharePoint 2013 lists using REST API and Angularjs. I am able to fetch the data successfully from one of the SharePoint list but my requirements is to fetch the data from multiple lists on the page load. I am using a provider hosted app to fetch the data from host web. I have 2 methods for calling 2 separate lists. I am getting the results from first method successfully but when the second method is called after the execution of 1st method. I am getting a time out error. It seems like i cannot call the 2 methods one after the other. Below is my code, could anyone please help me if i am missing something or if there is any other way to fetch the data from multiple SharePoint lists.
Method 1: fetch Data from List 1
var query = listEndPoint + "/getbytitle('CandidateList')/items?$select=ID,FirstName,MiddleInitial,LastName,EmailAddress,PrimaryPhoneNo,ProfileImage,Address,State,Country,CurrentTitle,CurrentCompany,LastActivityModifiedBy,LastActivityModifiedDate,DeletedStatus&@target='" + hostweburl + "'";
var getCandidates = function (query, queryCandidateNotes)
{
alert('getRequest');
var scriptbase = hostweburl + "/_layouts/15/";
var deferred = $q.defer();
// Load 15hives js files and continue to the successHandler
$.getScript(scriptbase + "SP.Runtime.js",
function () {`enter code here`
$.getScript(scriptbase + "SP.js",
function () {
$.getScript(scriptbase +"SP.RequestExecutor.js",
function () {
var executor = new SP.RequestExecutor(appweburl);
executor.executeAsync({
url: query,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: successHandler,
error: errorHandler
});
//deferred.resolve();
});
});
});
function successHandler(data) {
var jsonObject1 = JSON.parse(data.body);
deferred.resolve(jsonObject1);
}
function errorHandler(data, errorCode, errorMessage) {
alert('Error1:' + errorMessage + data.body);
}
// Get
return deferred.promise;
//Candidate Details Ends
};
Method 2: fetch Data from List 2
var queryCandidateNotes = listEndPoint + "/getbytitle('CandidateNotes')/items?$select=Title,CandidateId&@target='" + hostweburl + "'";
// Get All Candidate Notes
var getCandidateNotes = function (queryCandidateNotes) {
alert('getCandidateNotesRequest');
var scriptbase = hostweburl + "/_layouts/15/";
var deferred2 = $q.defer();
// Load 15hives js files and continue to the successHandler
$.getScript(scriptbase + "SP.Runtime.js",
function () {
$.getScript(scriptbase + "SP.js",
function () {
$.getScript(scriptbase + "SP.RequestExecutor.js",
function () {
var executor = new SP.RequestExecutor(appweburl);
executor.executeAsync({
url: queryCandidateNotes,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: successHandler,
error: errorHandler
});
//deferred.resolve();
});
});
});
function successHandler(data) {
var jsonObject2 = JSON.parse(data.body);
//var results2 = jsonObject2.d.results;
deferred2.resolve(jsonObject2);
//alert('2nd success:' + jsonObject2);
//return jsonObject2;
}
function errorHandler(data, errorCode, errorMessage) {
alert('Error2 :' + errorMessage + data.body);
}
// Get
return deferred2.promise;
};
Method 3: Calling method 2 after method 1
var getRequest = function (query, queryCandidateNotes) {
var deferred = $q.defer();
$.when(getCandidates(query, queryCandidateNotes)).then(function (data) {
alert('Success1:' + data);
$.when(getCandidateNotes(queryCandidateNotes)).then(function (data1) {
deferred.resolve(data);
alert('Success2:' + data1);
});
})
return deferred.promise;
};
return {
getRequest: getRequest
};
}]);
})();
$.when
is not appropriate here, utilize $q.all
that combines multiple promises into a single promise that is resolved when all of the input promises are resolved.
Example
app.controller('listController', function ($scope, $q, listService) {
SP.SOD.executeFunc('SP.RequestExecutor.js', 'SP.RequestExecutor', function () {
$q.all([listService.getListItems('Documents'), listService.getListItems('Site Pages')]).then(function (data) {
$scope.documentsItems = data[0].d.results;
$scope.sitePagesItems = data[1].d.results;
});
});
});
where listService
is a service for getting list items:
app.factory('listService', ['$q', function ($q) {
var getListItems = function (listTitle) {
var d = $q.defer();
JSRequest.EnsureSetup();
var hostweburl = decodeURIComponent(JSRequest.QueryString["SPHostUrl"]);
var appweburl = decodeURIComponent(JSRequest.QueryString["SPAppWebUrl"]);
var queryUrl = appweburl + "/_api/SP.AppContextSite(@target)/web/lists/getByTitle('" + listTitle + "')/items?@target='" + hostweburl + "'";
var executor = new SP.RequestExecutor(appweburl);
executor.executeAsync({
url: queryUrl,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function(data, textStatus, xhr) {
d.resolve(JSON.parse(data.body));
},
error: function(xhr, textStatus, errorThrown) {
d.reject(JSON.parse(xhr.body).error);
}
});
return d.promise;
};
return {
getListItems: getListItems
};
}]);
Default.aspx
<asp:Content ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
<script type="text/javascript" src="../Scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<SharePoint:ScriptLink Name="sp.js" runat="server" OnDemand="true" LoadAfterUI="true" Localizable="false" />
<meta name="WebPartPageExpansion" content="full" />
<!-- Add your CSS styles to the following file -->
<link rel="Stylesheet" type="text/css" href="../Content/App.css" />
<!-- Add your JavaScript to the following file -->
<script type="text/javascript" src="../Scripts/listService.js"></script>
<script type="text/javascript" src="../Scripts/App.js"></script>
</asp:Content>
and
<asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server">
<div ng-app="SPApp" ng-controller="listController">
</div>
</asp:Content>
App.js
'use strict';
(function() {
var app = angular.module('SPApp', ['SPApp.services']);
app.controller('listController', function ($scope, $q, listService) {
executeOnSPLoaded(function () {
$q.all([listService.getListItems('Documents'), listService.getListItems('Site Pages')]).then(function (data) {
$scope.documentsItems = data[0].d.results;
$scope.sitePagesItems = data[1].d.results;
});
});
});
})();
function executeOnSPLoaded(loaded) {
JSRequest.EnsureSetup();
var hostweburl = decodeURIComponent(JSRequest.QueryString["SPHostUrl"]);
var scriptbase = hostweburl + "/_layouts/15/";
$.when(
//$.getScript(scriptbase + "SP.Runtime.js"),
$.getScript(scriptbase + "SP.js"),
$.getScript(scriptbase + "SP.RequestExecutor.js"),
$.Deferred(function (deferred) {
$(deferred.resolve);
})
).done(function () {
loaded();
});
}
listService.js
'use strict';
angular.module('SPApp.services',[])
.factory('listService', ['$q', function ($q) {
var getListItems = function (listTitle) {
var d = $q.defer();
JSRequest.EnsureSetup();
var hostweburl = decodeURIComponent(JSRequest.QueryString["SPHostUrl"]);
var appweburl = decodeURIComponent(JSRequest.QueryString["SPAppWebUrl"]);
var queryUrl = appweburl + "/_api/SP.AppContextSite(@target)/web/lists/getByTitle('" + listTitle + "')/items?@target='" + hostweburl + "'";
var executor = new SP.RequestExecutor(appweburl);
executor.executeAsync({
url: queryUrl,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function(data, textStatus, xhr) {
d.resolve(JSON.parse(data.body));
},
error: function(xhr, textStatus, errorThrown) {
d.reject(JSON.parse(xhr.body).error);
}
});
return d.promise;
};
return {
getListItems: getListItems
};
}]);