I think the most useful information you provided above was your blocking analysis.
The user scrolls down (and based on the jQuery(window).on('scroll', load_data_from_database); more than one scroll event is fired.
Suppose two scroll events fire almost at the same moment.
Both calls to the load_data_from_database function
The first event checks if window.lock false (the answer is correct, so if the instruction is correct)
The second event checks if window.lock false (the answer is correct, so if the instruction is correct)
Immediately, this tells me that you have come to a general (and rather intuitive) misunderstanding.
Javascript is asynchronous, but asynchronous code does not match parallel code. As far as I understand, “asynchronous” means that function routines are not necessarily examined in depth order, as expected in synchronous code. Some function calls (those that you call "ajax") are queued and executed later. This may lead to some confusing code, but nothing gets confused how to think that your asynchronous code is running at the same time. "Concurrency" (as you know) when instructions from different functions can alternate with each other.
Solutions like locks and semaphores are the wrong way to think about asynchronous code. Promises are the right way. This is what makes programming on the Internet fun and cool.
I do not promise a guru, but here is a working fiddle that (I think) demonstrates a fix.
load_data_from_database = function () { // Load data from the database. Only load data if we almost reach the end of the page if ( jQuery(window).scrollTop() >= jQuery(document).height() - jQuery(window).height() - 300) { console.log(promise.state()); if (promise.state() !== "pending") { promise = jQuery.ajax({ type: 'post', url: '/echo/json/', data: { json: { name: "BOB" }, delay: Math.random() * 10 }, success: function (response) { console.log("DONE"); } }); } } }; var promise = new $.Deferred().resolve(); // The jQuery ready function (start code here) jQuery(document).ready(function() { jQuery(window).on('scroll', load_data_from_database); });
I use the global promise to ensure that the ajax part of your event handler is called only once. If you scroll up and down in the fiddle, you will see that when processing an ajax request, new requests will not be executed. Once the ajax request is complete, new requests can be made again. With any luck, this is the behavior you were looking for.
However, there are some pretty important caveats for my answer: the implementation of jQuery promises is known to be broken. It’s not just what people say that it’s great, it’s actually very important. I would suggest using a different promise library and mixing it with jQuery. This is especially important if you are just starting to learn about promises.
EDIT . In a personal note, I was recently in the same boat as you. Just 3 months ago, I thought that some of the event handlers that I used alternated. I was stunned and don't believe it when people started telling me that javascript is single-threaded. Which helped me understand what happens when a dismissal occurs.
In synchronous coding, we are accustomed to the idea of a "stack" of "frames", each of which represents a function context. In javascript and other asynchronous programming environments, the stack is complemented by a queue. When you raise an event in your code or use an asynchronous request like this $.ajax call, you $.ajax event in this queue. The event will be processed the next time the stack becomes clear. For example, if you have this code:
function () { this.on("bob", function () { console.log("hello"); }) this.do_some_work(); this.trigger("bob"); this.do_more_work(); }
The two functions do_some_work and do_more_work will be launched one after another at once. Then the function will end, and the event you set up in the queue will trigger a new function call (on the stack) and "hello" will appear in the console. Things get more complicated if you fire an event in a handler, or if you fire an event in a subroutine.
It's all good and good, but when everything starts to get really shitty, this is when you want to handle the exception. Once you enter the asynchronous earth, you will leave the beautiful oath of "function must return or quit." If you are in an event handler and you throw an exception, where will it be caught? It,
function () { try { $.get("stuff", function (data) {
won't save you now. promises allow you to return this ancient and powerful oath, giving you a way to combine your callbacks and control where and when they return. That way, with good API promises (not jQuery), you bind these callbacks in such a way that you can create pending errors and control the execution order. These, in my opinion, are beauty and magic promises.
Someone will stop me if I completely disconnect.