Divide promise chain into individual functions

Split into two separate functions:

public valJson(json, schemaFile: string) {
    return new Promise((resolve, reject) => {
        this.http.get(schemaFile)
            .toPromise()
            .then(fileContents => fileContents.json())
            .then((schema) => {
                let ajv = new Ajv({allErrors: true});
                ajv.validate(schema, json) ? 
                resolve() :
                reject(new Error("JSON does not conform to schema: " + ajv.errorsText()));
            }, err => reject(
                new Error("Unable to get schema file contents:" + err))
            );
    });
};

This function actually performs 3 distinct tasks which makes it difficult to unit test.

  1. Retrieve file contents
  2. Parse the contents to JSON
  3. Validate the JSON data

How could we break down this function to enable unit testing for each task?

An initial attempt at separating the validation part is not progressing as intended:

public valJson(json, schemaFile: string) {
    return new Promise((resolve, reject) => {
        this.http.get(schemaFile)
            .toPromise()
            .then(fileContents => fileContents.json())
            .then((schema) => {
                this.valJ(schema)
            }, err => reject(
                new Error("Unable to get schema file contents:" + err))
            );
    });
};

valJ(schema, json) {
    let ajv = new Ajv({ allErrors: true });
    if (ajv.validate(schema, json)) 
        return resolve();
    reject(new Error("JSON does not conform to schema: " + ajv.errorsText()));
}

Update - Based on feedback, making an effort to avoid using anonymous functions and then attempting to eliminate creating a new promise. Progress so far:

public valJson(json, schemaFile: string) {
    return new Promise((resolve, reject) => {
    var getFilePromise = this.http.get(schemaFile)
            .toPromise();
    var parseToJsonPromise = getFilePromise
            .then(contents => this.toJson(contents));
    var validateJsonPromise = parseToJsonPromise.then(schema => this.valJ(schema, json, resolve, reject),
            err => reject(
                new Error("Unable to get schema file contents:" + err))
            );
    });
};

toJson(fileContents): any {
    return fileContents.json();
}

valJ(schema, json, resolve, reject): any {
    let ajv = new Ajv({ allErrors: true });
    ajv.validate(schema, json) ?
        resolve() :
        reject(new Error("JSON does not conform to schema: " + ajv.errorsText());
    );
}

Answer №1

Here is one approach that can be taken:

function validateJsonData(json, schemaFile) {
  return fetchSchemaData(schemaFile)
    .then(res => parseSchemaData(res))
    .then(schema => validateWithDataSchema(json, schema));
}

function fetchSchemaData(url) {
  return fetchDataFromUrl(url).toPromise();
}

function parseSchemaData(response) {
  return response.json();
}

function validateWithDataSchema(json, schema) {
  let ajv = new Ajv({allErrors: true});
  if (!ajv.validate(schema, json)) {
    throw new Error("The JSON data does not match the specified schema: " + ajv.errorsText())
  }
}

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

The Kendo Grid is not displaying any data when trying to bind the data source using an ajax callback to the controller

My query is quite similar in nature to this: Binding Kendo Data Source with Async $.ajax calling from C# MVC Controller Action Below is the javascript code used for generating the Kendo grid: $(document).ready(function () { $("#grid").kendo ...

What is the best way to connect a string to a scoped variable in a view?

I'm looking to connect a string to a scope variable that will be determined by user input in an input field located within a specific view. The goal is for the combined string and scope variable value to appear in another div within the view. Here&ap ...

Retrieve the properties of an object

I have a JavaScript program where I retrieve values from a JSON file and store them in an array. However, when I attempt to access the elements of this array, it returns nothing. Below is the function that pushes temperatures: temperatures = [] get_info ...

What could be causing Jquery's $.ajax to trigger all status codes even when the call is successful?

Here is a simple Jquery ajax function call I have. function fetchData(){ var jqxhr = $.ajax({ url: "../assets/js/data/users.json", type: "GET", cache: true, dataType: "json", statusC ...

Is Sending an Object to a Function in the Same Scope Inefficient?

Is there a noticeable delay when passing around an object within the same scope? Let's explore Option 1 and Option 2. In Option 1, we work directly with the object, while in Option 2 we follow better encapsulation practices. However, if we were to sti ...

Tips on using CSS to hide elements on a webpage with display:none

<div class="span9"> <span class="disabled">&lt;&lt; previous</span><span class="current numbers">1</span> <span class="numbers"><a href="/index/page:2">2</a></span> <span class="num ...

Reducing the slide margins in impress.js?

When using Impress.js, I noticed that the default slides have a large left margin (or padding - it's hard to determine with Firefox's Inspector). I have a slide with a wide <pre> block that would fit if it were aligned to the left, but it d ...

Verify if input is selected using jQuery

Is it possible to achieve the following using jQuery? if($(this).parent().find('input:checked') == true) {$(this).find('.switch').attr('state','on');} else{$(this).find('.switch').attr('state',& ...

I am hoping this script will activate a JavaScript function rather than simply greeting

I stumbled upon a working script, but I must stress that my knowledge of JQuery is quite limited. Here's the script in question: document.getElementById("id_of_button").onclick = function() {clickFunction()}; function clickFunction() {alert("hello") ...

Identifying line breaks caused by browsers or CSS forced line breaks

<p style="width:60px"> This is just a sample text. It is a piece of text that doesn't really say anything meaningful.</p> When this text is rendered as HTML, it would look like this: This is just a sample text. It is a piece of text ...

Error encountered while rendering a functional component in ReactJS

Recently, I've been utilizing functional components in my project, like this: const Component = (props) => <div>asdasdasd</div>. However, I'm encountering a cryptic error when trying to render my application. The console displays a ...

What is the process for adjusting the code to manage the labels of specific buttons?

There is a code $("button").click(function() { var btn = this; if (btn.loaded) { $(btn).prev("div").html(btn.originalContent); btn.loaded = false; $(btn).text('Get Dynamic chart'); } else { btn.originalConte ...

Typescript and Apollo Client return types intertwined

My goal is to create a simple function within a class that generates an Apollo Client. Below is the code I have implemented: import appConfig from 'config/app-config'; import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/clie ...

Disabling Babel in Nuxt.js: A Step-by-Step Guide

I've come to the decision to eliminate Babel transpilation from my projects, as I no longer see the need to accommodate pre-ES6 era browsers. However, my search efforts have yielded no results on how to go about this. My Nuxt project is currently fill ...

Modifications to the selected input do not impact the current state of the model

Declare 3 select inputs with hierarchical data to be chosen: <select data-ng-model="current.manufacturer" data-ng-options="c.name for c in manufactures"></select> <select data-ng-model="current.mark" data-ng-options="c.name for c in current ...

Tips for consistently obtaining the executed value of a getter in Mongoose?

In my mongoose schema, I have implemented a getter function for one of the properties as shown below: const User = new mongoose.Schema( { active: Boolean, email: {type: String, get: toLowerCase} } ) The toLowerCase function is def ...

Utilize jQuery to apply inline styles to dynamically created div elements

I am attempting to apply inline styles to a div using jQuery. The current state of the div, as seen in Firebug, is shown below: https://i.sstatic.net/rqhIc.jpg My goal is to retain the existing CSS while adding margin-left:0 and margin-right:0 to the cur ...

Unable to conceal an Ajax loading image that is dynamically inserted within my web application

I have been working on a project using asp.net web application, and within it, I am attempting to accomplish the following tasks: Calling 2 REST APIs Displaying an AJAX loading image Creating a list of the results Hiding the loading image Below is the c ...

Is it possible to hide and reveal specific form elements based on the selection of a checkbox?

Having issues with the code provided below, it's not working as expected. Can you help me figure out what I might be missing? HTML: <input id="id_code_col" type="checkbox" name="code_col"></input> SCRIPT: $(document).ready(function(){ ...

Executing a time-consuming function call within the componentDidMount lifecycle method of a React component

When working with my React component, I utilize the componentDidMount function to pass a string received through props to a processing function. This function then returns another string which is used to update the component's state. import React, { C ...