Backbone causes a sudden influx of unexpected AJAX requests

I included the fetch URL with a deferred method, expecting it to only make one remote AJAX request.

However, I noticed that it is being called three times when the page loads.

Does anyone know how to resolve this issue? Thank you

JS Scripts


var Comments = Backbone.Collection.extend({
    model: Comment,
    url: fetch_comments_url,
    initialize: function() {
        this.fetch({
            success: this.fetchSuccess,
            error: this.fetchError
        });
        this.deferred = new $.Deferred();
    },
    deferred: Function.constructor.prototype,
    fetchSuccess: function(collection, response) {
        collection.deferred.resolve();
    },
    fetchError: function(collection, response) {
        throw new Error("Products fetch did not get collection from API");
    }
});

var comments = new Comments();

...

comments.deferred.done(function() {
    commentView.render();
    emptyCommentView.render();
});

Complete JS Scripts


var Comments = Backbone.Collection.extend({
    model: Comment,
    url: fetch_comments_url,
    initialize: function() {
        this.fetch({
            success: this.fetchSuccess,
            error: this.fetchError
        });
        this.deferred = new $.Deferred();
    },
    deferred: Function.constructor.prototype,
    fetchSuccess: function(collection, response) {
        collection.deferred.resolve();
    },
    fetchError: function(collection, response) {
        throw new Error("Products fetch did not get collection from API");
    },
    wellFormedComments: function () {
        var MESSAGE_LIMIT_LENGTH = 80;
        var models = comments.select(function (model) {
          var msg = model.get("message");
          if (msg != null) {
            msg = msg.replace(/^\s+|\s+$/g, '');
            if (msg.length >= MESSAGE_LIMIT_LENGTH) {
              model.set("preview_message", msg.substr(0, MESSAGE_LIMIT_LENGTH/2));
            } else{
              
            };
            return true;
          }
          else{
              return false;
          };
        });
        return new Comments(models);
    },
    emptyComments: function () {
        var models = comments.select(function (model) {
          var msg = model.get("message");
          return false === _(msg).notBlank();
        });
        return new Comments(models);
    }
});

var comments = new Comments();

var CommentView = Backbone.View.extend({
    el: $("#comments_section"),
    render: function() {
        var notNullComments = comments.wellFormedComments();
        if (notNullComments.length > 0) {
            $("#dadasay_comments_plugin").show();
        }
        var html = commentsTmpl(notNullComments.toJSON());
        $(this.el).append(html);
    }
});

var EmptyCommentView = Backbone.View.extend({
    el: $("#empty_comments_list"),
    render: function() {
        var source = $('#empty_comments_list_tmpl').html();
        var emptyComments = comments.emptyComments();
        var html = emptyCommentsTmpl(emptyComments.toJSON());
        $(this.el).html(html);
    }
});

var commentView = new CommentView({collection: comments});
var emptyCommentView = new EmptyCommentView({collection: comments});

comments.deferred.done(function() {
    commentView.render();
    emptyCommentView.render();
});

Answer №1

The issue is that the comments collection triggers the fetch method when initialized. The methods wellFormedComments and emptyComments also create new comments collections, which in turn trigger fetch.

You can resolve this by manually triggering fetch as needed, for example:

var Comments = Backbone.Collection.extend({
  model: Comment,
  url: fetch_comments_url,
  wellFormedComments: function() {
    var MESSAGE_LIMIT_LENGTH = 80
    var models = this.select(function(model) {
      var msg = model.get("message")
      if (msg != null) {
        msg = msg.replace(/^\s+|\s+$/g, '')
        if (msg.length >= MESSAGE_LIMIT_LENGTH) {
          model.set("preview_message", msg.substr(0, MESSAGE_LIMIT_LENGTH / 2));
        } else {};
        return true
      } else {
        return false
      };
    });
    return new Comments(models);
  },
  emptyComments: function() {
    var models = this.select(function(model) {
      var msg = model.get("message")
      return false === _(msg).notBlank();
    });
    return new Comments(models);
  }
});
var CommentView = Backbone.View.extend({
  el: $("#comments_section"),
  render: function() {
    var notNullComments = comments.wellFormedComments();
    if (notNullComments.length > 0) {
      $("#dadasay_comments_plugin").show();
    }
    var html = commentsTmpl(notNullComments.toJSON());
    $(this.el).append(html);
  },
});
var EmptyCommentView = Backbone.View.extend({
  el: $("#empty_comments_list"),
  render: function() {
    var source = $('#empty_comments_list_tmpl').html();
    var emptyComments = comments.emptyComments();
    var html = emptyCommentsTmpl(emptyComments.toJSON());
    $(this.el).html(html);
  },
});
var comments = new Comments();
var commentView = new CommentView({
  collection: comments
});
var emptyCommentView = new EmptyCommentView({
  collection: comments
});

comments.fetch({ // <--------- Call this manually once
  success: function() {
    commentView.render();
    emptyCommentView.render();
  },
  error: function() {}
});

To better structure your code, consider the following changes with explanatory comments:

var Comments = Backbone.Collection.extend({
  model: Comment,
  url: fetch_comments_url,
  wellFormedComments: function() {
    var MESSAGE_LIMIT_LENGTH = 80
    var models = this.select(function(model) {
      var msg = model.get("message")
      if (msg != null) {
        msg = msg.replace(/^\s+|\s+$/g, '')
        if (msg.length >= MESSAGE_LIMIT_LENGTH) {
          model.set("preview_message", msg.substr(0, MESSAGE_LIMIT_LENGTH / 2));
        }
        return true
      }
      return false

    });
    return new Comments(models);
  },
  emptyComments: function() {
    var models = this.select(function(model) {
      var msg = model.get("message")
      return false === _(msg).notBlank();
    });
    return new Comments(models);
  }
});
var CommentView = Backbone.View.extend({
  el: $("#comments_section"),
  template: commentsTmpl, // reference to the template
  initialize: function() {
    this.render(); // call render on initialization
  },
  render: function() {
    if (this.collection.length) { 
      $("#dadasay_comments_plugin").show(); 
    }
    var html = this.template(this.collection.toJSON());
    this.$el.append(html);
  },
});
var EmptyCommentView = Backbone.View.extend({
  el: $("#empty_comments_list"),
  template: emptyCommentsTmpl,
  initialize: function() {
    this.render();
  },
  render: function() {
    var html = this.template(this.collection.toJSON());
    this.$el.html(html);
  },
});
var comments = new Comments();

comments.fetch({ // <--------- Call this manually once
  success: function(collection, response) {
    var commentView = new CommentView({
      collection: collection.wellFormedComments()
    });
    var emptyCommentView = new EmptyCommentView({
      collection: collection.emptyComments()
    });
  },
  error: function() {}
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

After being awaited recursively, the resolved promise does not perform any actions

When working with the Twitter API, I need to make recursive method calls to retrieve tweets since each request only returns a maximum of 100 tweets. The process is straightforward: Call the function and await it Make an HTTP request and await that If the ...

Managing "unprocessed information" in a Node.js environment and transferring the information through a Node Express endpoint

Currently, I am in the process of making an API call to retrieve a file using axios: async function fetchData() { const configuration = {}; // { responseType: 'stream'}; const { response } = await axios.get(URL, configuration); c ...

Webpack encounters an error while attempting to load Bootstrap v4.0.0-beta

I've encountered an issue with my webpack configuration and Bootstrap v4.0.0-alpha.6 that was working fine until I attempted to switch to v4 beta. Unfortunately, I can't seem to get it working properly now :( Here is a snippet of my config: w ...

Using jQuery to handle multiple AJAX XML requests

Currently, I am working on developing a JavaScript XML parser using jQuery. The idea is that the parser will receive an XML file containing information along with multiple links to other XML files. As the parser runs, it will identify tags within the file ...

Troubles with data tables, pagination, and selecting rows

My application features a datatable with pagination. When a user selects a row in the table, a report is displayed below it that can be edited. If the user attempts to select another row without saving any pending edits, they are given a warning and the op ...

Check out the enhanced image gallery feature in Fancybox 3 with the ability

The documentation for Fancy box 3 provides some basic examples of its AJAX capabilities. My goal is to create a button that, when clicked, will load a "gallery" of images fetched from an AJAX response. I came across an example (the last one on this page) ...

Angular 7: Finding the variance between array elements

How can I subtract the values from the first 3 rows of the table? The formula is TVA Collectée - TVA Déductible - TVA Déductible/immo If the result is positive, it should be displayed in the box labeled TVA à Payer. If it's negative, it should g ...

Exploring the capabilities of Google Apps Script for looping and generating output

I have two spreadsheets named rawData and processedData. The content of rawData is as follows: Status Title Options Live Title1 Option1, Option2, Option3, Option4 Live Title2 Option1, Option2, Option3, Option4, Option5 Live Title3 Option1, O ...

Guide on sending MySQL query results as JSON data using Ajax

I'm having trouble figuring out how to pass the results of a MySQL query into an HTML page using AJAX and JSON. I have the following code in ajax2.php: $statement = $pdo->prepare("SELECT * FROM posts WHERE subid IN (:key2) AND Poscode=:postcode2") ...

Activate NavLink based on multiple paths leading to the same component

There are two routes ("/" and "/home") that display the same component: const router = createBrowserRouter([ { path: "/", element: <ContentWrapper />, errorElement: <p>404</p>, children: [ ...

In what time frame is Javascript/AJAX functioning?

Do you know if the times are measured in milliseconds or seconds? I'm puzzled why these two scripts aren't synchronizing - there's a significant delay. $(document).ready(function() { $("#idle").delay(300000).fadeIn(500); }); var interv ...

Steps for invoking a Polymer dialog within a JavaScript function

Dealing with Javascript scopes has always been a struggle for me. My goal is to display a loading dialog while waiting for a JSON response, as shown below: toQueueRequest.onreadystatechange = function () { if (toQueueRequest.readyStat ...

What is the best way to automatically add a date and timestamp to every new entry?

I am currently working on a project that utilizes AngularJS and Ionic frameworks. The main feature of the project will involve users inputting data to create a list, and allowing any user to comment on each item in the list. One challenge I have encounter ...

The DOM element fails to load when utilizing the ng-view attribute

Recently, I have started working with AngularJS for my first web application and everything is running smoothly. However, I am now looking to integrate some charts using jQuery. The issue arises when trying to load a chart upon clicking on a menu item in ...

Is it possible to implement a "load more" feature with JSON data using the getJSON method?

Currently, I am working on the task of extracting objects from a JSON file and arranging them in a grid layout similar to masonry using Salvattore. While I successfully utilized this helpful tutorial to retrieve the data, my next challenge is to implement ...

specialized html elements within data-ng-options

I have a code snippet where I am populating select options from a controller using data-ng-options. However, I would also like to include an icon with each option. For example, I want to append <span class="fa fa-plus"></span> at the end of e ...

Basic Hover Effect in Javascript

Looking at this snippet of HTML: <div id="site-header-inner"> <div id="header-logo"> <?php echo wp_get_attachment_image(get_field('header_logo','options'),'full'); ?> </div> <div id= ...

positioning the cursor at the end of a content-editable div

When working with a contenteditable div, I encountered several issues specific to FireFox. To address these problems, I found that appending a br tag to the end of the div was necessary. <div id="testDiv" contentEditable="true"> Hey, click the butt ...

Output a variable that is generated from invoking an asynchronous function

I'm currently in the process of developing an application that is going to leverage the capabilities of a SOAP server through the use of the https://github.com/vpulim/node-soap module. One of the main challenges I am facing is how to efficiently crea ...

Optimal approach for fetching data in a Next.js component

I am facing a challenge with my menu component that is displayed globally. What is the most effective way to populate this component with data? I am exploring the static generation feature provided by Next.js, but all of the data fetching recommendations ...