How to load data in breaks from Ajax call? - javascript

Guys I have an ajax call on my page, which is being called on scroll down event (lazy loading).
This is the whole call :
function callMoreData()
{ $.ajax( {
type: "GET",
url: "/api/values/getnotice",
dataType: "json",
crossDomain: true,
async: true,
cache: false,
success: function (data) {
updateData(data);
},
error: function (x, e) {
alert('problem while fetching records!');
} });}
function updateData(data) {
updateData = function (data) { };
$.each(data, function (index, value) {
BindNotice(value);
});
}
function BindNotice(values)
{
...appending some div here with values...
}
now this call is returning all the data and display it all at once on first scroll event. What I want to do is, load the data in sets of two. For example, each loop gets executed on index 0 and 1 at first scroll, then on second scroll index 2 and 3 gets processed and then so on. How would I do about doing as? I have a very limited experience with JS/AJAX...
EDIT : CODE FROM CUSTOM LIBRARY :
$(".mainwrap .innnerwrap").mCustomScrollbar({
autoDraggerLength:true,
autoHideScrollbar:true,
scrollInertia:100,
advanced:{
updateOnBrowserResize: true,
updateOnContentResize: true,
autoScrollOnFocus: false
},
callbacks:{
whileScrolling:function(){WhileScrolling();},
onTotalScroll: function () {
callMoreData();
}
}
});
WebApi CODE :
[WebMethod]
[HttpGet]
public List<Notice> GetNotice()
{
string con = ConfigurationManager.ConnectionStrings["conn"].ConnectionString;
SqlConnection Connection = new SqlConnection(con);
string Query = "uSP_GetAllNotice";
SqlCommand cmd = new SqlCommand(Query, Connection);
cmd.CommandType = CommandType.StoredProcedure;
DataTable dt = new DataTable();
Connection.Open();
dt.Load(cmd.ExecuteReader());
Connection.Close();
List<Notice> objNoticeList = new List<Notice>();
foreach (DataRow row in dt.Rows)
{
Notice objNotice = new Notice();
objNotice.Subject = row["subject"].ToString();
objNotice.Date = Convert.ToDateTime(row["IssueDate"]);
objNotice.Department = row["Department"].ToString();
objNotice.Body = row["Body"].ToString();
objNotice.NoticeImage = row["NoticeImage"].ToString();
objNotice.Icon = row["Icon"].ToString();
objNoticeList.Add(objNotice);
}
return objNoticeList;
}

First of all, you have to make sure the server-side delivers only as mutch elements as you like, so that would be something like
[...]
type: "GET",
url: "/api/values/getnotice/" + start + '/' + amount,
dataType: "json",
[...]
start and amount have to be defined outside the function, in a higher scope, so it's available by the ajax function. While amount will be more or less constant, start can be calculated.
One option would be, to increment it on the success function.
Another solution can be, to count the divs you already appended to your DOM.
The result could be something like:
var amount = 2;
var start = 0;
function callMoreData(){
$.ajax( {
type: "GET",
url: "/api/values/getnotice/" + start + '/' + amount,
dataType: "json",
crossDomain: true,
async: true,
cache: false,
success: function (data) {
updateData(data);
start += amount;
},
error: function (x, e) {
alert('problem while fetching records!');
}
});
}
I recommend NOT to put it in the global namespace, but to put it in a own one.

Maybe you can use paging parameters to get your data in chunks of two items at a time. Let the server handle the work of figuring out how to break the response data into two items per page.
$.ajax({
type: "POST",
url: "/api/values/getnotice",
data: {
'PageSize': pageSize,
'Page': page
},
type: "GET",
dataType: "json",
crossDomain: true,
async: true,
cache: false,
success: function (data) {
updateData(data);
},
error: function (x, e) {
alert('problem while fetching records!');
}
});

Make a global variable such as
Var time_scrolled = 0; //in the beginning
when you receive scrolldown event your indexes at each request will be (time_scrolled*2) and (time_scrolled*2+1) then you increase time_scrolled by 1 as time_scrolled++;
Hope this will solve your problem.
Edited:
complete code
Var times_scrolled = 0; //in the beginning
Var global_data = [];
function callMoreData()
{ $.ajax( {
type: "GET",
url: "/api/values/getnotice",
dataType: "json",
crossDomain: true,
async: true,
cache: false,
success: function (data) {
global_data = data;
},
error: function (x, e) {
alert('problem while fetching records!');
} });}
callMoreData(); //fetch data at the time of loading since it won't miss at first scroll
function updateData(){
var initial = times_scrolled*2;
var final = initial+1;
for(var i=initial;i<data.length && i<=final;i++)
{
BindNotice(global_data[i]);
}
times_scrolled++;
}
function BindNotice(values)
{
...appending some div here with values...
}
// modify custom library code to:
$(".mainwrap .innnerwrap").mCustomScrollbar({
autoDraggerLength:true,
autoHideScrollbar:true,
scrollInertia:100,
advanced:{
updateOnBrowserResize: true,
updateOnContentResize: true,
autoScrollOnFocus: false
},
callbacks:{
whileScrolling:function(){WhileScrolling();},
onTotalScroll: function () {
updateData();
}
}
});

This is what I did to solve my problem. This is my ajax call
function callMoreData() {
var RoleCodes = $('#hiddenRoleCode').val();
$.ajax(
{
type: "GET",
url: "/api/alert/getalerts?RoleCode=" + RoleCodes + "&LastAlertDate=" + formattedDate,
dataType: "json",
crossDomain: true,
async: true,
cache: false,
success: function(data) {
$.each(data.data, function (index, value) {
update();
BindAlert(value);
});
},
error: function(x, e) {
alert('There seems to be some problem while fetching records!');
}
}
);
}

Related

Multiple Ajax Request waits each other to run

I try to send multiple ajax requests. But each request waits for previous one complete to start.
Is there any reason for that?
Here is my JS code.
tjq.ajax({
type: 'POST',
data: { id: _id },
dataType: 'json',
url: '/dynamic-packages?act=addtocart',
success: function (r) {
///...
}
});
Here is the C# code. I just put a sleep for 10 sec to demonstrate duration in developer console.
protected void Page_Load(object sender, EventArgs e) {
if (Request["act"] == "addtocart")
{
Thread.Sleep(10000);
Response.End();
}
}
As you can see the SS duration increases by 10 sec for each request.
UPDATE:
Here is how I call ajax request
for (var i = 0; i < Destinations.length; i++) {
getHotels(i);
}
Use async statement for give prority in first or next it.
Setting async to false means that the statement you are calling has to complete before the next statement in your function can be called. If you set async: true then that statement will begin it's execution and the next statement will be called regardless of whether the async statement has completed yet.
async: false
function getData1(){
var data;
var param1 = jQuery('field1').val();
var param2 = jQuery('field2').val();
jQuery.ajax({
url: "ajx_request1.php",
type: 'POST',
data: {
'field1': param1,
'field2': param2
},
dataType: "json",
async: false,
success: function(result){
data=result;
},
error: function(result) {
alert("Error");
}
});
return data;
}
function getData2() {
var data;
var param1 = jQuery('field1').val();
var param2 = jQuery('field2').val();
jQuery.ajax({
url: "ajx_request2.php",
type: 'POST',
data: {
'field1': param1,
'field2': param2
},
dataType: "json",
async: false,
success: function(result){
data=result;
},
error: function(result) {
alert("Error");
}
});
return data;
return data;
}
getData1();
getData2();
You Can Also Set Timeout for response get late another from one statement.
setTimeout(function() {
var data = getData2();
console.log("The data is: " + data);
},1000);

Javascript clearTimeout not working even with timer Variable Available To All Functions

I have read almost every thread on here about clearing a JS timer and nothing seems to be working. Here's the code
$(document).ready(function() {
var timeout;
$('#chat_link').click(function() {
var id = str_replace('chat_', '', $(this).attr('alt'));
$.ajax({
async: false,
type: 'POST',
url: '/members/functions/private_message_handler.php',
dataType: 'json',
data: 'member=' + id + '&action=get_old_messages',
success: function(data, textStatus) {
$('#chat_name').html(data.name);
$('#message_area').html(data.messages);
$('#chat_window').show();
$('#message_area').animate({
scrollTop: $('#message_area').get(0).scrollHeight
}, 100);
$('#message_member_id').val(id);
}
});
get_messages(id, timeout);
});
$('#close_chat').click(function() {
$('#chat_window').hide();
$('#chat_name').html('');
$('#message_area').html('');
clearTimeout(timeout);
});
(function($) {
get_messages = function(member_id, timeout) {
var time = 3000;
timeout = setTimeout(
function() {
$.ajax({
async: false,
type: 'POST',
url: '/members/functions/private_message_handler.php',
dataType: 'json',
data: 'member=' + member_id + '&action=get_old_messages',
success: function(data, textStatus) {
$('#message_area').html(data.messages);
$('#message_area').animate({
scrollTop: $('#message_area').get(0).scrollHeight
}, 100);
get_messages(member_id);
}
});
},
time
);
};
})(jQuery);
});
As you can see I made the timeout variable outside of all the functions so everything could 'see' it and I even tried passing it to the get_messages function. No matter what I do when the chat box is closed ($('#close_chat').click(function()) the script keeps running. I'm not sure what I am doing wrong but obviously something isn't right
timeout = setTimeout(...) in your get_messages function changes the value of your local variable timeout, and not the one defined at the very beginning of your script. Primitive types are passed by value in javascript, you can't pass them by reference.
You can store your timeout id inside an object and pass this object instead of the primitive value. Also you need to cancel the next request when you close your chat.
$(document).ready(function() {
var options = {
timeout: null,
isChatVisible: false
};
$('#chat_link').click(function() {
options.isChatVisible = true;
var id = str_replace('chat_', '', $(this).attr('alt'));
$.ajax({
async: false,
type: 'POST',
url: '/members/functions/private_message_handler.php',
dataType: 'json',
data: 'member=' + id + '&action=get_old_messages',
success: function(data, textStatus) {
$('#chat_name').html(data.name);
$('#message_area').html(data.messages);
$('#chat_window').show();
$('#message_area').animate({
scrollTop: $('#message_area').get(0).scrollHeight
}, 100);
$('#message_member_id').val(id);
}
});
get_messages(id, options);
});
$('#close_chat').click(function() {
$('#chat_window').hide();
$('#chat_name').html('');
$('#message_area').html('');
clearTimeout(options.timeout);
options.isChatVisible = false;
});
(function($) {
get_messages = function(member_id, options) {
var time = 3000;
options.timeout = setTimeout(
function() {
$.ajax({
async: false,
type: 'POST',
url: '/members/functions/private_message_handler.php',
dataType: 'json',
data: 'member=' + member_id + '&action=get_old_messages',
success: function(data, textStatus) {
// stop polling the server if chat is closed
if (!options.isChatVisible) {
return;
}
$('#message_area').html(data.messages);
$('#message_area').animate({
scrollTop: $('#message_area').get(0).scrollHeight
}, 100);
get_messages(member_id, options);
}
});
},
time
);
};
})(jQuery);
});

How to pass a list of id's in a AJAX request to the Server in MVC

In a AJAX request to the server in MVC, how can I pass a list of id's to the controller's action function?
I accept with or without use of Html helpers.
I know MVC's model binder has no problem when it comes to simple types like int, string and bool.
Is it something like I have to use and array instead in the action?
I don't care if I have to use an array or List and even if the strings I int or strings I can always convert them. I just need them on the server.
My List ids gives null at the moment.
Javascript:
var ids= [1,4,5];
// ajax request with ids..
MVC Action:
public ActionResult ShowComputerPackageBuffer(List<int> ids) // ids are null
{
// build model ect..
return PartialView(model);
}
EDIT: Added my AJAX request
$(document).ready(function () {
$('#spanComputerPackagesBuffer').on('click', function () {
var ids = $('#divComputerPackagesBuffer').data('buffer');
console.log('bufferIds: ' + bufferIds);
var data = {
ids: ids
};
var url = getUrlShowComputerPackageBuffer();
loadTable(url, "result", data);
});
});
// AJAX's
function loadTable(url, updateTargetId, data) {
var promise = $.ajax({
url: url,
dataType: "html",
data: data
})
.done(function (result) {
$('#' + updateTargetId).html(result);
})
.fail(function (jqXhr, textStatus, errorThrown) {
var errMsg = textStatus.toUpperCase() + ": " + errorThrown + '. Could not load HTML.';
alert(errMsg);
});
};
// URL's
function getUrlShowComputerPackageBuffer() {
return '#Url.Action("ShowComputerPackageBuffer", "Buffer")';
};
SOLUTIONS: // Thanks to #aherrick comment. I missed the good old "traditional"
$.ajax({
type: "POST",
url: '#Url.Action("ShowComputerPackageBuffer", "Buffer")',
dataType: "json",
traditional: true,
data: {
bufferIds: bufferIds
}
});
Use the traditional parameter and set it to true.
$.ajax({
type: "POST",
url: "/URL",
dataType: "json",
traditional: true,
data: {}
});
Try this one (I've checked it):
$(function () {
var ids = [1, 4, 5];
$.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
url: '#Url.Action("YourAction", "YourController")',
data: JSON.stringify( { ids: ids })
}).done(function () {
});
});
You have to make sure your contentType is application/json and your data is stringified.
public ActionResult SaveSomething(int[] requestData)
//or
public ActionResult SaveSomething(IEnumerable<int> requestData)
Using Action Result you cannot receive JSON object:
Using Controler:
[HttpPost]
[Route( "api/Controller/SaveSomething" )]
public object SaveTimeSheet( int[] requestData )
{
try
{
doSomethingWith( requestData );
return new
{
status = "Ok",
message = "Updated!"
};
}
catch( Exception ex )
{
return new
{
status = "Error",
message = ex.Message
};
}
}
java script:
var ids = [1,4,5];
var baseUrl: 'localhost/yourwebsite'
$.ajax({
url: baseUrl + '/api/Controller/SaveSomething',
type: 'POST',
data: JSON.stringify(ids),
dataType: 'json',
contentType: 'application/json',
error: function (xhr) {
alert('Error: ' + xhr.statusText);
},
success: function (result) {
if (result != undefined) {
window.location.href = window.location.href;
}
},
async: false,
});

How can I make sure that other functions is run after this get function is fully completed and rendered?

I have this script that adds elements with data by a get json function.
$(document).ready(function() {
ADD.Listitem.get();
});
It basicly adds a bunch of html tags with data etc. The problem I have is following:
$(document).ready(function() {
ADD.Listitem.get();
var arr = [];
$(".Listitem-section-item-title").each(function() {
arr.push($(this.text()));
});
});
-
get: function(web) {
AST.Utils.JSON.get("/_vti_bin/AST/ListItem/ListitemService.svc/GetListItem", null, AST.Listitem.renderListitem);
},
renderListitem: function(data) {
$("#Listitem-template").tmpl(data["ListItemResults"]).prependTo(".ListItem-section-template");
}
and here is the json get:
ADD.Utils.JSON.get = function (url, data, onSuccess) {
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
async: true,
url: url,
data: data,
cache: false,
dataType: "json",
success: onSuccess,
error: ADD.Utils.JSON.error,
converters: { "text json": ADD.Utils.JSON.deserialize }
});
}
The array each loop is not running beacuse the get method is not finished with rendering the Listitem-section-item-title selector so it cant find the selector.
Is there any good solutions for this?
You could change your functions to return the promise given by $.ajax :
ADD.Utils.JSON.get = function (url, data) {
return $.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
async: true,
url: url,
data: data,
cache: false,
dataType: "json",
converters: { "text json": ADD.Utils.JSON.deserialize }
}).fail(ADD.Utils.JSON.error);
}
get: function(web) {
return AST.Utils.JSON.get("/_vti_bin/AST/ListItem/ListitemService.svc/GetListItem", null).done(AST.Listitem.renderListitem);
},
So that you can do
$(document).ready(function() {
ADD.Listitems.get().done(function(){
var arr = [];
$(".Listitem-section-item-title").each(function() {
arr.push($(this.text()));
});
});
});
Callback:
$(document).ready(function() {
ADD.Listitem.get(url,data,function(){
var arr = [];
$(".Listitem-section-item-title").each(function() {
arr.push($(this.text()));
});
});
});
Without callback:
If you cant get the get method to take a callback or return a promise then I think the best way will be to check when its done.
$(document).ready(function() {
ADD.Listitem.get();
var timer = setInterval(function(){
if ($("#thingWhichShouldExist").length>0){
var arr = [];
$(".Listitem-section-item-title").each(function() {
arr.push($(this.text()));
});
clearInterval(timer);
}
},50);
});
Retrieve the values and on success, call a function which will push the values into the array.
Also, arr.push($(this.text())); should be arr.push($(this).text());.

How can I run Ajax functions synchronously from Javascript?

I have the following code:
$('#DoButton').click(function (event) {
event.preventDefault();
$("input:checked").each(function () {
var id = $(this).attr("id");
$("#rdy_msg").text("Starting" + id);
doAction(id);
});
});
function doAction(id) {
var parms = { Id: id };
$.ajax({
type: "POST",
traditional: true,
url: '/adminTask/doAction',
async: false,
data: parms,
dataType: "json",
success: function (data) {
$("#rdy_msg").text("Completed: " + id);
},
error: function () {
var cdefg = data;
}
});
}
When the button is clicked it checks the form and for each checked input it calls doAction() which then calls an Ajax function. I would like to make it all synchronous with a 2 second delay between the completion of one call and the running of the next. The delay is to give the user time to see that the last action has completed.
By setting async=false will that really make the ajax function wait?
How can I add a 2 second wait after the Ajax has run and before the next call to doAction?
There is option in jQuery to set the ajax function synchronous
$.ajaxSetup({
async: false
});
To make the function to wait you can use .delay()
Try the solution of this question also.
Try to do it using recursion
$('#DoButton').click(function (event) {
event.preventDefault();
doAction( $("input:checked").toArray().reverse() );
});
function doAction(arr) {
if( arr.length == 0 ) return;
var id = arr.pop().id;
$("#rdy_msg").text("Starting" + id);
$.ajax({
type: "POST",
traditional: true,
url: '/adminTask/doAction',
async: false,
data: { Id: id },
dataType: "json",
success: function (data) {
$("#rdy_msg").text("Completed: " + id);
setTimeout(function(){ doAction(arr); }, 2000);
},
error: function () {
var cdefg = data;
$("#rdy_msg").text("Error: " + id);
setTimeout(function(){ doAction(arr); }, 2000);
}
});
}
Use setTimeout for the AJAX call doAction.

Categories

Resources