Tuesday 23 May 2017

NodeJS: promise returned by Promise.all is not resolved although the individual promises are

I have the following discovery code using the mdns-js package.
in ./lib/deviceDiscovery.js:

var mdns = require('mdns-js');
const browsers = new Map();
const INFINITE = -1;

function createABrowser(theServiceType, timeout) {
    if (browsers.has(theServiceType)) {
        return;
    }

    return new Promise(function(resolve, reject) {
        var browser = mdns.createBrowser(theServiceType);
        browser.on('ready', function() {
            browsers.set(theServiceType, browser);
            resolve(browser);
        });

        if (timeout != INFINITE) {
            setTimeout(function onTimeout() {
                try {
                    browser.stop();
                    browsers.delete(browser.serviceType);
                } finally {
                    reject('browser ' + browser.toString() + ' timed out.');
                }
            }, timeout);
        }
    });
}

module.exports.startService = function(services, timeout) {
    timeout = timeout || INFINITE;
    promises = [];
    services.forEach(function(service) {
        promises.push(createABrowser(service, timeout));
    });
    return Promise.all(promises);
}

module.exports.stopService = function() {
    browsers.values().forEach(function(browser) {
        browser.stop();
    });
    browsers.clear();
}

module.exports.getDevices = function() {
    if (browsers.size == 0) {
        reject('service was stopped');
    } else {
        const promises = [];
        for (let browser of browsers.values()) {
            promises.push(new Promise(function(resolve, reject) {
                try {
                    browser.discover();
                    browser.on('update', function(data) {
                        mfps = new Set();
                        const theAddresses = data.addresses;
                        theAddresses.forEach(function(element) {
                            mfps.add(element);
                        });
                        resolve(mfps);
                    });
                } catch(err) {
                    reject(err);
                }
            }));
        };
        return Promise.all(promises).then(function(values) {
            return new Set(values);
        }, function(reason) {
            return reason;
        });
    }
}

and use it in another file like this:

const DeviceDiscoveryService = require('./lib/deviceDiscovery');
var co = require('co');

co(function *service() {
    yield DeviceDiscoveryService.startService([internetPrinter, pdlPrinter, unixPrinter], TIMEOUT);
    yield DeviceDiscoveryService.getDevices();
}).catch(onerror);

function onerror(err) {
    // log any uncaught errors
}

The problem is that the second yield hangs; it seems that the promise returned by getDevices function isn't resolved indefinitely, although I see that the individual promises are resolved.

startService uses a similar Promise.all(...) but it works ok.

Another related question is about the mdns-js: it seems that for each (input) service, the browser receives multiple updates. But I resolve the promise for each browser after the first update event... do I need to wait for multiple updates and how?
Any hints will be greatly appreciated! Thanks.



via sharpthor

No comments:

Post a Comment