aka aka - 3 months ago 9
Javascript Question

How to use nested promise to call function and get value

I am new to asynchronous call and promise. i want to call three function which calls database. i need to get those results and process it. i use promise for it. it doesn't work as i am thinking i must be not doing right way please suggest. your any answer is appreciated. i am using in NODE JS.
database function seems working it calls database with three query.

CODE

function nested_three_Promise_call_three_function(){
new Promise(function (resolve, reject) { return sample(); })
.then(
function (val) {
new Promise(function (resolve, reject) { sample1(); })
.then(
function (val) {
new Promise(function (resolve, reject) { sample2(); })
.then({
function(val) {
/* NEED TO GET VALUE OF ALL SAMPLE,SAMPLE1,SAMPLE 2 FOR FURTHER PROCESS BEFORE SEND TO RESPONSE*/
console.log("sample" + sample);
console.log("sample1" + sample1);
console.log("sample2" + sample2);
},
function(err){
console.log("error inside promise for sample2");
}
})
},
function (err) {
console.log("error inside promise for sample1");
}
)
},
function (error) {
console.log("error inside promise for sample1");
});
}

function sample() {
console.log("sample called");
database.query("select * from sample").then(function(result){
sample = result;
}).catch(function(error){
console.log("error occured in sample")
});

}
function sample1() {
console.log("sample called");
database.query("select * from sample1").then(function(result){
sample1 = result;
}).catch(function(error){
console.log("error occured in sample1")
});
}
function sample2() {
console.log("sample called");
database.query("select * from sample2").then(function(result){
sample2 = result;
}).catch(function(error){
console.log("error occured in sample2")
});
}

Answer

There are several issues there:

  1. Your sampleX functions don't return anything.

  2. Your sampleX functions should just return the promises query returns.

  3. You're creating promises unnecessarily.

So the first thing to do is change:

function sample() {
    console.log("sample called");
    database.query("select * from sample").then(function(result){
        sample  = result;
    }).catch(function(error){
        console.log("error occured in sample")
    });
}

to:

function sample() {
    console.log("sample called");
    return database.query("select * from sample");
}

...and similarly for sample1 and sample2.

If, as suggested by the code in your question, none of the functions uses the result of any of the others, they you can use Promise.all:

function nested_three_Promise_call_three_function() {
    Promise.all([sample(), sample1(), sample2()])
        .then(function(results) {
            // Use results[0], results[1], and results[2] here
            console.log("From sample:",  results[0]);
            console.log("From sample1:", results[1]);
            console.log("From sample2:", results[2]);
        })
        .catch(function(error) {
            // Something went wrong
        });
}

function sample() {
    console.log("sample called");
    return database.query("select * from sample");
}
function sample1() {
    console.log("sample called");
    return database.query("select * from sample1");
}
function sample2() {
    console.log("sample called");
    return database.query("select * from sample2");
}

The database calls will run in parallel, and then you'll get the result when they're all done.


If they each need the result of the previous one, and you only need the final result at the end, then you chain them; in the below, note that sample1 and sample2 now accept an argument:

function nested_three_Promise_call_three_function() {
    sample()
        .then(sample1)
        .then(sample2)
        .then(function(result) {
            // `result` is the result from sample2
        })
        .catch(function(error) {
            // Something went wrong
        });
}

function sample() {
    console.log("sample called");
    return database.query("select * from sample");
}
function sample1(arg) {
    console.log("sample called");
    // use arg here
    return database.query("select * from sample1");
}
function sample2(arg) {
    console.log("sample called");
    // use arg here
    return database.query("select * from sample2");
}

If you need to pass previous results into subsequent functions and have all of the results at the end, you probably have several options, but the first thing that comes to mind is just to keep track of them where you make the calls:

function nested_three_Promise_call_three_function() {
    let sampleResult, sample1Result;
    sample()
        .then(function(result) {
            sampleResult = result;
            return sample1(result);
        })
        .then(function(result){
            sample1Result = result;
            return sample2(result);
        })
        .then(function(sample2Result) {
            // `sampleResult`, `sample1Result`, and `sample2Result` have the results here
        })
        .catch(function(error) {
            // Something went wrong
        });
}

function sample() {
    console.log("sample called");
    return database.query("select * from sample");
}
function sample1(arg) {
    console.log("sample called");
    // use arg here
    return database.query("select * from sample1");
}
function sample2(arg) {
    console.log("sample called");
    // use arg here
    return database.query("select * from sample2");
}