NodeJS:Promise.all返回的保证未解决,尽管个别承诺是

时间:2017-05-24 00:59:07

标签: javascript node.js promise mdns

我使用mdns-js包有以下发现代码 在 ./ 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;
        });
    }
}

并在另一个文件中使用它:

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
}

问题是第二个产量挂起;看来 getDevices 函数返回的承诺无法无限期地解决,尽管我看到个别承诺已经解决了。

startService 使用类似的Promise.all(...),但它可以正常工作。

另一个相关的问题是关于mdns-js:似乎对于每个(输入)服务,浏览器都会收到多个更新。 但是我在第一次更新事件后解决了每个浏览器的承诺...我是否需要等待多次更新以及如何进行? 任何提示将不胜感激!感谢。

1 个答案:

答案 0 :(得分:1)

我相信你共享更新会在任何时候从createABrowser返回一个promises(如果服务已经存在,则不返回undefined)。没有回复承诺,我认为Promise.all()不会解决。

相反,在顶部创建一个promise并解析服务是否已存在,并返回该承诺。

对于getDevices()调用,您还可以在不返回promise的情况下运行拒绝。这会有用吗?

module.exports.getDevices = function() {
    if (browsers.size == 0) {
        // Create a new promise, return it, and immediately reject
        return new Promise(function(resolve, reject) { reject('service was stopped') };
        // reject('service was stopped'); <- There wasn't a promise here
    } 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;
        });
    }
}