【问题标题】:NodeJS: promise returned by Promise.all is not resolved although the individual promises areNodeJS:Promise.all 返回的 Promise 未解决,尽管各个 Promise 已解决
【发布时间】:2017-10-24 03:25:05
【问题描述】:

我有以下使用 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
}

问题是第二个yield挂了;似乎 getDevices 函数返回的承诺并未无限期解决,尽管我看到各个承诺已解决。

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

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

【问题讨论】:

  • 我不太明白使用co() 的好处。如果你只做DeviceDiscoveryService.startService(.......).then(DeviceDiscoveryService.getDevices).then(console.log); 会发生什么

标签: javascript node.js promise mdns


【解决方案1】:

我相信您共享 update 始终从 createABrowser 返回一个承诺(如果服务已经存在,而不是返回 undefined )。如果不返回承诺,我认为 Promise.all() 将无法解决。

相反,如果服务已经存在,则在顶部创建一个 Promise 并解析,然后返回该 Promise。

对于 getDevices() 调用,您正在运行拒绝而没有在那里返回承诺。这行得通吗?

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;
        });
    }
}

【讨论】:

  • 我更新了服务已经存在的案例,tks。但是 startService 已经在工作了。未决的承诺是针对 getDevices 的,我更新它以在顶部返回一个 Promise,但是这个返回的承诺仍然挂起......
猜你喜欢
  • 2016-12-28
  • 2018-10-04
  • 1970-01-01
  • 2017-04-15
  • 2018-02-06
  • 1970-01-01
  • 2022-10-05
  • 1970-01-01
相关资源
最近更新 更多