0

I am learning promises in node js.I have written a piece of code as below.

var request = require("request");
var userDetails;

function getData(url) {
    // Setting URL and headers for request
    var options = {
        url: url,
        headers: {
            'User-Agent': 'request'
        }
    };
    // Return new promise 
    return new Promise(function (resolve, reject) {
        // Do async job
        request.get(options, function (err, resp, body) {
            if (err) {
                reject(err);
            } else {
                resolve(body);
            }
        })
    })
}

var errHandler = function (err) {
    console.log(err);
}

function main() {
    var userProfileURL = "https://api.githshub.com/users/narenaryan";
    var dataPromise = getData(userProfileURL);
    // Get user details after that get followers from URL
    var whichPromise = dataPromise.then(JSON.parse)
        .then(function (result) {
            userDetails = result;
            // Do one more async operation here
            console.log("then1")
            var anotherPromise = getData(userDetails.followers_url).then(JSON.parse);
            return anotherPromise;
        })
        .then(function (data) {
            return data
        });
    console.log(whichPromise)

    whichPromise.then(function (result) {
        console.log("result is" + result)

    }).catch(function (error) {
        console.log("Catch" + error)
    });
}


main();

Now this works just fine. I have queries in this regard.

1.How JSON.Parse able to parse data without getting json string in argument.

var whichPromise = dataPromise.then(JSON.parse)

2.If i put a wrong url in below line

var userProfileURL = "https://api.githshub.com/users/narenaryan";

then it's then block will not work because DNS will not be resolved & should get an error which means

 var anotherPromise = getData(userDetails.followers_url).then(JSON.parse);
            return anotherPromise;

will not return any value and whichPromise will not have any reference.

but if call below code

whichPromise.then(function (result) {
        console.log("result is" + result)

    }).catch(function (error) {
        console.log("Catch" + error)
    });

here whichPromise is able to call the catch block. can someone explain why ?

TechChain
  • 8,404
  • 29
  • 103
  • 228
  • You are just passing `JSON.parse` function as an argument see [`this`](https://stackoverflow.com/questions/5752030/passing-a-function-as-an-argument-in-a-javascript-function), its similar to writing `.then(x => JSON.parse(x))`, every promise should include a catch block at the end of `then` chains – Kunal Mukherjee Jun 14 '19 at 06:31
  • If you put a wrong `url` there will be an error `if (err) {reject(err); }` so `whichPromise ` is able to call catch block. IMO reject work like `throw error` but in asynchronous callback you must use reject instead of `throw error` – Burdy Jun 14 '19 at 06:44

2 Answers2

1

How JSON.Parse able to parse data without getting json string in argument.

var whichPromise = dataPromise.then(JSON.parse)

.then() expects you to pass it a function. When the promise resolves, it will call that function and pass it the resolved value of the promise.

So, you are passing it the JSON.parse function and then it will call that function and pass it the result value of the promise which will be your JSON string. The return value of executing that function will become the resolved value of the resulting promise in the chain. So, in your case the Javascript object that JSON.parse() returns becomes the resolved value of your promise chain.

If I put wrong URL in ...

A wrong URL will obviously not fetch the data you want. Depending upon the wrong URL, it will either create a networking error (such as DNS error resolving the host) or return a 404 error (no such path on that host) or the server could return some other type of response. What exactly gets returned from the request.get() depends upon the options you pass to request.get() and exactly how the URL is wrong. In some cases, the promise will get rejected and in that case your .then() handler will not get called. In other cases, the promise may still get resolved, but there will be no data or improper JSON passed to JSON.parse() result is some other error.

It's important to understand that getting back a 404 response code when you send an invalid path with an http request is NOT considered an http error by many libraries. You reached the server, you sent it a request, it processed that request and returned you a response. Though the response might be a 404 status code, that is not necessarily considered an error. So, your own code has to either configure the http library you're using to force a 404 or any 4xx to be an error or you have to explicitly check for that so you handle it properly.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • I understand the consequences if i URL is wrong and also reason for that but still thanks for your explanation. I want to know why catch block is getting called as whichPromise may not have reference as then block did not execute.I made URL wrong intentionally so that catch block can be executed. – TechChain Jun 14 '19 at 08:31
  • @DhirajKumar - If `getData()` rejects, then `dataPromise` will be a rejected promise and `dataPromise.then()` will be a rejected promise which means `whichPromise` will be a rejected promise so it will fire the `.catch()` handler. If `getData()` resolved to data that is not JSON, then `JSON.parse(badData)` will get called and whichPromise will still end up a rejected promise so it will fire its `.catch()` handler. Not sure what else you're asking. – jfriend00 Jun 14 '19 at 14:11
1

lets try to understand it step by step.

1

=> dataPromise.then(JSON.parse)

This is just equal to as writing

=> dataPromise.then(data => JSON.parse(data))

Because, JSON.parse is a method that takes some data (string) as first input, and returns parsed JS-Object. But, in a clear picture it's a pure function.

What in second line i did to clear your concept i passed anonymous arrow-function that also thats an arg (data) as first arg and returns what JS.parse() method returns. So, we are creating an extra layer or execution context. That extra context is called "point"

=> dataPromise.then(data => JSON.parse(data)) with-extra function layer

=> dataPromise.then(JSON.parse) passed JSON.parse directly (arg => parsedObj)

This example official software vocabulary is called "point-free programming".

isaadabbasi
  • 101
  • 5