Search code examples
javascriptnode.jspromisechain

How to chain a promise that calls another promise in node js


I'm new to node js, I'm trying to create a rest method that returns a list of objects, all was fine until I wanted to send the response, the logic does something like this:

  1. find objects
  2. init the objects
  3. push the object into a list
  4. send the list with the objects

what happens is that the point 3 is happening after the point 4 and I got an empty list, after research I found that is due to the async nature of node, I tried to rewrite the code using promises but I could not find an example of a promise that calls another promise

first version

app.get('/initDevices', (req, res) => {
    console.log('init devices.');
    cameras = [];
    onvif.startProbe().then((device_info_list) => {
        let requests = device_info_list.map((info) => {
            processDevice(info)
        });
        Promise.all(requests).then(() => {
            console.log('all done ');
            res.json(cameras);
        });
    }).catch((error) => {
        res.json('nothing');
    });
});

function processDevice(info) {
    return new Promise((resolve, reject) => {
        console.log("step 1");
        let device = new onvif.OnvifDevice();
        console.log("step 2");
        device.init().then((devinfo) => {
            console.log("step 3");
            cameras.push(devinfo);
            console.log("cameras: " + cameras.length);
            resolve("done");
        }).catch((error) => {
            reject("It broke");
        });
    });
}

output

 init devices.
 step 1
 step 2
 //response goes to the user with empty array []
 step 3 //push happens

second try (with promises)

function processDevice(info) {
    return new Promise((resolve) => {
        console.log("step 1");
        let device = new onvif.OnvifDevice();
        console.log("step 2");
        resolve(device);
    }).then((device) => {
       console.log("step 3");
        return device.init();
    }).then((device) => {
       console.log("step 4");
        return cameras.push(device);
    });
}

output

init devices.
step 1
step 2
step 3
//response goes to the user with empty array []
step 4 //push happens

I think this line return device.init(); makes the promise to finish but I do not know why.

Can someone help me to understand why the chain doesn't work as expected? what did I do wrong?

by the way, the examples that I followed are here but the operations are just some additions that do not invoke other promises

Edit: I found a better way to achieve this

function processDevice(info) {
    let device = new onvif.OnvifDevice();
    return device.init().then(() => {
        console.log("init done");
        cameras.push(camObj);
    });
}

since a promise was already being used, it was not necessary to wrap it around another


Solution

  • Your requests variable is undefined - you have to return the processDevice(info) inside the map like this:

    let requests = device_info_list.map((info) => {
                return processDevice(info)
            });