How can I generate a dummy JSON response using Backbone Fetch?

Exploring Backbone and looking for a way to simulate the response of a .fetch() call within a model without using a testing library or connecting to an external service.

If the setting in the model is this.options.mock === true, I'd like to use an internal JSON object as the fetch result. Otherwise, make a real AJAX request to the API.

However, it's not working as expected. The view renders properly with data from the API (real fetch), but doesn't display anything when using fake data. Is there a way to mimic a Fetch response in Backbone without relying on tools like Sinon?

Here's a snippet of the model code that handles fetching data and preparing it for rendering in a template, followed by how the view utilizes this model:

'use strict';
(function (app, $, Backbone) {

    app.Models.contentModel = Backbone.Model.extend({

        /**
         * Initializes model. Fetches data from API.
         * @param  {Object} options Configuration settings.
         */
        initialize: function (options) {
            var that = this;
            that.set({
                'template': options.template,
                'mock': options.mock || false
            });

            $.when(this.retrieveData()).then(function (data) {
                that.formatDataForTemplate(data);
            }, function () {
                console.error('failed!');
            });
        },

        // Remaining model logic goes here

})(window.app, window.jQuery, window.Backbone);

Relevant bit from the view (ContentView):

this.model = new app.Models.contentModel({template: this.templateName});
this.listenTo(this.model, 'dataFormatted', this.render);

Could it be that the data is being set too quickly before the listener is fully set up?

Answer №1

If you need to customize the fetch function, here's how you can do it.

var CustomizedModel = Backbone.Model.extend({
  initialize: function(attr, options) {
    if (options.customFetch) {
      this.fetch = this.customFetch;
    }
  },
  url: 'http://someUniqueURL.com',
  customFetch: function(options) {
    var self = this
    this.set({
      'title': 'Custom Title',
      'description': 'custom description',
      'position': 1,
      'byline': 'Publisher'
    });

    if (typeof options.success === 'function') {
      options.success(self, {}, {})
    }
  }
});
var customizedModel = new CustomizedModel(null, {
  customFetch: true
})
customizedModel.fetch({
  success: function(model, xhr) {
    alert(model.get('title'));
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Answer №2

The issue at hand does not lie in the implementation of retrieveData, but rather in how it is being invoked. By resolving the deferred before returning, you are essentially making it instantaneous. This results in formatDataForTemplate being executed while your model is still initializing.

Therefore, when you execute

this.model = new app.Models.contentModel({template: this.templateName});
this.listenTo(this.model, 'dataFormatted', this.render);

The dataFormatted event gets triggered before the listener has been registered.

One possible solution is to introduce a timeout, which can be achieved simply by

setTimeout(function() {
    deferred.resolve(mock);
});

This will delay the resolution until the next iteration of the event loop, ensuring that the listener is in place.

Alternatively, you could refrain from calling retrieveData during model initialization and instead have the view handle it after attaching its listeners.

this.model = new app.Models.contentModel({template: this.templateName});
this.listenTo(this.model, 'dataFormatted', this.render);
this.model.retrieveData();

I personally prefer the latter approach, but if the goal is solely to mock data for offline use, either solution would suffice in my opinion.

In a separate context, it's worth mentioning that the actual definition for initialize on a model is

new Model([attributes], [options])
. Therefore, your initialize function should probably take the following form:

initialize: function (attributes, options) {
    var that = this;
    that.set({
        'template': options.template,
        'mock': options.mock || false
    });

This adjustment is mainly for improved readability. Consequently, since you are passing only one object, there should be no need to call set at all.

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

Obtain data from a single module and incorporate it into a different one

In my Angular 2 application, I am dealing with two component files - home.ts and folder-selector.ts. Within the folder-selector.ts file, there is a variable named pathToNode. I am trying to figure out how to access this value from within the home.ts file ...

The ReactDom reference is not defined when working with React and webpack

After following a tutorial on React and webpack from jslog.com, I encountered issues with using updated syntax such as using ReactDom to call render instead of the deprecated 'React.renderComponent'. I tried running: npm install --save react-do ...

Changing the contents of a global array in JavaScript

$(document).ready(function(){ var currArray=null; var group=null; var admin=null; var equipment=null; var student=null; console.log("after get array info"); for(var i=0; i<equipment.length; i++) { console.log("equipment at index after get array info ...

The date error from day.js in Firefox is not valid

My date is formatted as 2022-01-27 09:23:48 UTC and I am trying to parse it into MMMM-DD-YYYY format (Jan-27-2022) using day.js. The parsing works well in Chrome, but Firefox returns an 'Invalid' result. import dayjs from "dayjs" const ...

Progressive reloading page with Jquery Ajax upload

I've encountered a strange issue with a Jquery form submit. After the upload completes, the page reloads even though the server hasn't finished processing. The server only returns a JSON success status, so it's not an issue on the server s ...

Creating a sort button in HTML that can efficiently sort various divs within a table is a useful tool for enhancing user experience

My HTML table is populated with various <td> elements. How can I arrange these divs based on IMDb rating, TomatoMeter, etc... [ CSS code is not provided below ] <table> <tr class="row"> <td class="column"> <br> ...

Strange Behavior of Delayed Responses in jQuery's Ajax Calls

Dealing with jQuery AJAX requests can be tricky, especially when the response is delayed. If I'm sending a request every second and the response takes, let's say, 3 seconds to come back, the success method of AJAX gets triggered. In Chrome Linu ...

Emulate sequelize using Jest in combination with sequelize-mock

In my latest project, I have been implementing TDD as the primary methodology along with integration tests. One of the tasks at hand is to retrieve all users from the database. //controller.js const UserService = require('../services/user'); mod ...

Envelop a HTML element within another HTML element with the help of jQuery

Unique link Here is some sample HTML: <div><img src="http://i.imgur.com/4pB78ee.png"/></div> I am looking to use jQuery to wrap the img tag with an a tag, like this: $(function() { var a = '<a href="http://i.imgur.com/4pB78e ...

The looping function in JavaScript iterates 20 times successfully before unexpectedly producing NaN

run = 0 function retrieveItemPrice(id){ $.get('/items/' + id + '/privatesaleslist', function(data){ var htmlData = $(data); var lowestPrice = parseInt($('.currency-robux', htmlData).eq(0).text().replace(',& ...

Setting up Jest

I'm currently attempting to integrate the Jest Testing framework into my React Native project. Unfortunately, I am encountering an error message: Failed to retrieve mock metadata: /Users/me/Documents/Development/project/node_modules/global/window.js ...

Why is it important to have specific property names?

Here is some code and HTML for triggering a radio button. It seems to work fine without any issues, but I'm wondering if the presence of a name property is necessary. When I remove the name property, it stops working. Can someone explain why? <inp ...

The function Object.defineProperties() allows for reassigning a property's value after it has been initially

The issue arises in the initial code snippet provided below, specifically when dealing with the object book. Initially, the value of book.year is set to 2013. Even after updating the value by setting book.year = 2015, retrieving the value using book.year s ...

Reorganize child JSON objects into a new object that includes a parent ID

Exploring the realm of JavaScript, I am currently delving into Node.JS to interact with an API and save the data in a SQL Server. Utilizing the "request" and "mssql" Node packages for this task as they possess robust documentation and support. My query re ...

The PropertyOverrideConfigurer encountered an issue while processing the key 'dataSource' - The key 'dataSource' is invalid, it was expecting 'beanName.property'

During the installation of Sailpoint on Oracle, the configuration properties are as follows: ##### Data Source Properties ##### dataSource.maxWaitMillis=10000 dataSource.maxTotal=50 dataSource.minIdle=5 #dataSource.minEvictableIdleTimeMillis=300000 #dataSo ...

Sending data from jQuery in an HTML document to a PHP script

Struggling to pass a variable from jQuery to a PHP file and encountering some difficulties. Below is a basic HTML file named "send.html". <html> <head> <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script ...

Spotfire: Changing a URL in an input field after it has been entered by the user

Currently, I am faced with a challenge related to importing a file in spotfire based on the path provided by the user. To accomplish this, I am utilizing a data function written in R script. In R, it is essential to note that all "\" characters are n ...

The catch block seems to be failing to capture the errors thrown by the fetch API

I am facing an issue with my code where the fetch method, enclosed within a catch block, fails to capture errors. Despite attempting various error handling approaches on my node backend, the problem persists. https://i.stack.imgur.com/0reJj.png const e ...

NodeJS: Extract images based on specified coordinates

Dealing with images that contain text can be a challenge, but by using tesseract and the imagemagick node module, I was able to extract the text successfully. The only issue I encountered was related to the image size. Fortunately, cropping out the releva ...

Is combining Passport.js Google authentication with JWT a logical choice?

I am currently working on integrating Google Login with Passport.js into my MERN stack application. However, I have created this middleware for JWT authentication: const jwt = require("jsonwebtoken"); const config = require("config"); module.exports = a ...