javascript utilize bluebird promise to asynchronously retrieve the first file from a given list

I am currently working on implementing promises in JavaScript to retrieve the first available file from a list of paths (for example, ["c:\\temp\\test1.json", "c:\\temp\\test2.json"]). The goal is to identify and return the first file that exists on disk, such as c:\temp\test2.json.

function getFirstFile(paths) {

    if (!paths || paths.length == 0) {
        return {};
    }

    // sequential async search (recursive)
    var filePath = paths.shift();
    return fs.readFileAsync(filePath)
        // found = stop searching
        .then(function (content) {
            return new Promise (function (resolve, reject) {
                resolve(JSON.parse(content));
            })
        })
       // continue searching further paths left in the list
       .error(function (err) {
            return getFirstFile(paths);
       });
 }    

var paths2 = ["c:\\temp\\test1.json", "c:\\temp\\test2.json"];

getFirstFile(paths2)
    .then( function (index) {
        assert.equal(index.file, ".test2.json");
    })
    .error( function(err) {
        assert.fail(err.toString());
    });

Despite the fact that the file "C:\temp\test2.json" is indeed present, it seems like the fs.readFileAsync(filePath) function doesn't trigger the .then(function (content) {

It's almost as though there's an uncaught exception or similar issue with the promise. What do you think could be causing this?

Answer №1

Upon testing, it was discovered that the code below functions properly without Mocha testing implemented. However, when integrated with Mocha testing, the test consistently passes regardless of the contents of test2.json.

var fs = require('fs');
var Promise = require('bluebird');  //faster than standard Chrome promises
if (typeof fs.readFileAsync === "undefined") {Promise.promisifyAll(fs);}  
var path = require('path');

function getFirstFile(paths) {

    if (!paths || paths.length == 0) {
        return {};
    }
    
    var filePath = paths.shift();
    return fs.readFileAsync(filePath)
        .then(function (content) {
            return new Promise (function (resolve, reject) {
                resolve(JSON.parse(content));
            })
        })
        .error(function (err) {
            return getFirstFile(paths);
        })
        .catch(function (e) {
            return getFirstFile(paths);
        });
}

var paths2 = ["c:\\temp\\test1.json", "c:\\temp\\test2.json"];

getFirstFile(paths2)
.then( function (index) {
    console.log(JSON.stringify(index));
})
.error( function(err) {
    console.log(err);
});

The issue lies in how the Mocha test was executed, as shown by the incorrect and correct test code examples:

Incorrect implementation (Mocha test always passes due to promise resolving after the test):

it('My Test', function () {    
    utils.getFirstFile(["c:\\temp\\test1.json", "c:\\temp\\test2.json"])
    .then(function(index) {
        assert.equal(index.file, ".test2.json");
    })
    .catch( ....);
}

Correct implementation involves returning a promise:

it('My Test', function () {    
    return utils.getFirstFile(["c:\\temp\\test1.json", "c:\\temp\\test2.json"])
        .then(function(index) {
             assert.equal(index.file, ".test2.json");
        });
}

Answer №2

Indeed, it is probable that the commitment ultimately ended up declining (most likely due to an error thrown by JSON.parse), yet as a result of this

   .error(function (err) {
        return getFirstFile(paths);
   });

The decline would be intercepted, prompting the function to run once more, and again. It would continuously iterate in a loop, never actually reaching the point of rejection. It is imperative to allow the promise to reject.

Answer №3

When it comes to handling errors, the .error() method is designed to "only catch operational errors". Keep in mind that an exception thrown by JSON.parse won't be caught using this method. Instead, consider utilizing the .catch() method, especially in your final handler where you call assert.fail.

function getFirstFile(paths) {
    if (!paths || paths.length == 0) return {};

    // Perform a sequential asynchronous search (recursive)
    var filePath = paths.shift();
    return fs.readFileAsync(filePath)
    .then(JSON.parse)
    .catch(function (err) {
        return getFirstFile(paths);
    });
}

getFirstFile(["c:\\temp\\test1.json", "c:\\temp\\test2.json"])
.then(function(index) {
    assert.equal(index.file, ".test2.json");
})
.catch(function(err) {
    assert.fail(err.toString());
});

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

Watching for changes to an object's value in an AngularJS service triggered by a controller from a separate module (Extended Edition)

Referring to this discussion on Stack Overflow: AngularJS trigger and watch object value change in service from controller The original question was about watching for changes in a service from a controller. I am interested in extending this concept to ...

What causes the closure variable to be reset after iterating over JSON data using $.each method?

Take a look at this scenario: var elements = []; $.getJSON(data_url, function(result) { $.each(result, function(key, value) { elements.push(parser.read(value.data)); // at this point, "elements" contains items }); }); dataLayer.addElements( ...

Utilizing Data From External Sources in a React Application

I have encountered an issue with displaying data from another page in a reusable table I created using React. Specifically, I am having trouble getting the value to be shown in <TableCell> Please check out this code sandbox link for reference ACCES ...

Different method for adding child elements to the DOM

When creating a DOM element, I am following this process: var imgEle = document.createElement('img');     imgEle.src = imgURL;             x.appendChild(imgEle); Instead of appending the last line which creates multiple img elements ev ...

Having trouble getting NextJS to work with jsmpeg/node-rtsp-stream for displaying an RTSP stream

Exploring: https://github.com/kyriesent/node-rtsp-stream and How to display IP camera feed from an RTSP url onto reactjs app page? I attempted to showcase the RTSP stream from a CCTV but encountered an error. ReferenceError: document is not defined at scri ...

combine various types of wrappers in React

We're embarking on a fresh project with React, and we will be utilizing: React Context API i18n (react.i18next) GraphQL (Apollo client) Redux CSS-in-JS (styled-components or aphrodite) The challenge lies in each of these implementations wrapping a ...

Steps to successfully retrieve an image using JavaScript on the client side while circumventing any CORS errors

I have a React application where I am displaying an image (an SVG) and I want the user to be able to download it by clicking on a button. The image is stored in Firebase Storage. However, I am encountering an issue with CORS error: Access to fetch at &ap ...

It's next to impossible to secure expedited work on an ongoing project using Vercel

Yesterday, I successfully deployed an application on Vercel using only ReactJS. Today, I made the decision to develop an API for my application, To clarify, I have a folder housing the React app, and within that, I created a directory named "api" followi ...

What is the best way to use Python and Selenium to click on an angularjs link by comparing it to the text entered by the user?

A user can input a specific link that they would like to click. For example, if the user inputs "Tampa Bay Downs" for the variable track. In my Python Selenium test program, I will search for the following code: <a ng-click="updateFavorite()(raceInfo. ...

How can one efficiently navigate through extensive functions without risking surpassing the stack limit?

I am currently developing an application in Node.js that requires numerous configuration and database calls to process user data. The problem I am facing is that after reaching 11,800+ function calls, Node throws a RangeError and exits the process. The er ...

Troubleshooting VueJS's Dilemma with Quotation Marks

When I try to parse a string containing either double quotes or single quotes, an error is being thrown: JSON Unexpected token. Is there a way to properly parse and bind it to a variable in Vue.js? PHP $arr = array(); $arr[0]['description'] = ...

Ways to utilize JavaScript to identify if a flash is launching in a separate tab

On my website, I have embedded a third-party flash player using an iframe. Whenever a user clicks on a specific area within the flash player, a new tab is opened in the browser. I am trying to track the frequency of this occurrence. However, I have encoun ...

How to upload a document to Alfresco using JavaScript API

I am facing an issue while attempting to upload a file from a node application to my local Alfresco server. I have been able to login, create, and delete folders successfully, but I am encountering difficulties when trying to upload files. let AlfrescoApi ...

What is the method for displaying a canvas scene within a designated div element?

I need help displaying a scene inside an existing div on my webpage. Whenever I try to do this, the canvas is always added at the top of the page. I attempted to use getElementById but unfortunately, it didn't work as expected. What could I be overlo ...

Utilizing PHP to dynamically load HTML forms and leveraging JQuery for form submissions

I am currently facing a dilemma that I am unsure how to approach. It seems that JQuery requires unique ID's in order to be called in the document ready function. I use PHP to read my MySQL table and print out HTML forms, each with a button that adds a ...

How can a row in AG-Grid be updated without causing a refresh?

I am working on adding a custom radio button feature for users to select a row. Currently, I have the following code: const Cell = (cellProps) => { const { data, node, api } = cellProps const selectedRow = () => { let { isChecked } = data ...

Pass data in JSON format from Laravel controller to AngularJS

When working with Laravel, I successfully converted data in MySQL to JSON for use in AngularJS. However, I am now unsure of how to effectively utilize these values in AngularJS. Can anyone offer assistance? View output data (hide each value) https://i.ss ...

JavaScript layout: Thymealf

I have a unique thymeleaf template like so: <body> <div id="layout"> <!-- Menu toggle --> <a href="#menu" id="menuLink" class="menu-link"> <!-- Hamburger icon --> <span>& ...

What is the best way to verify the presence of # in a URL?

Every now and then, due to caching issues, I find myself adding a # to my URL, like so: http://www.example.com/#lang=3201954253 My goal is to find and remove the #lang from the URL if it is present. ...

Retrieving radio button values in React from a different component

I am dealing with a child component that contains radio buttons, each with its own value. I have imported this child component into a parent component to manage its state from the parent component. With the child component added, I need to access all the i ...