【问题标题】:Async HTTP(S) Traversal only using Node.js Promisses仅使用 Node.js Promises 的异步 HTTP(S) 遍历
【发布时间】:2016-10-26 21:54:15
【问题描述】:

我尝试遍历一堆 HAL/JSON 资源,这些资源对通过 href 连接并通过 https 检索的项目树进行建模。 IE。一个“项目”可能是一个叶子或带有其他叶子的另一个分支。 唉,我做错了。遍历将始终结束,即在完全递归完成之前,在我的代码示例的最后一条语句中点击 then() 回调。实际上,我只在 children 中恢复了第一层。

我的问题:我错过了什么才能做到正确?

我还在学习 Nodejs,但我已经在前面的示例中成功使用了 Promise。我在这里问这个问题,因为我不得不只使用模块 https 和集成的 Nodejs 东西。其他示例确实经常使用其他模块 和/或不解决我遇到的问题。

var traverse = function(rootItemUrl, depth, children) {
    var deferred = Promise.defer();

    var itemUrl = rootItemUrl;
    var options = {
        'path'      : itemUrl
        , 'host'      : "<host>"
        , 'method'  : 'GET'
        , 'headers' : {
            'Content-Type'  : 'application/json'
            , 'Accept'      : 'application/json'
            , 'Forwarded'   : 'proto=https;host=<host>'
            , 'Cookie'      : options_.headers['Cookie']
        }
    };

    https.get(options, onItemResultResponse);
    function onItemResultResponse(itemResultResponse) {
        var body = [];
        itemResultResponse.on('data', function onDataChunk(data) {
            body.push(data);
        });
        itemResultResponse.on('end', onItemResultData);
        itemResultResponse.on('error', onRequestItemsError);
        function onRequestItemsError(e) {
            console.log('Get items failed for <'+rootItemUrl+'>.');
            deferred.reject();
        }
        function onItemResultData() {
            var items = [];
            var itemResult = JSON.parse(Buffer.concat(body).toString());
            var embedded = itemResult._embedded;
            var collection = embedded ? embedded['collection'] : undefined;
            if(collection) {
                var itemsObject = collection._links['item'];
                if(itemsObject) {
                    if(itemsObject.length) {
                        for(var i = 0; i < itemsObject.length; ++i) {
                            items.push(itemsObject[i].href);
                        }
                    } else {
                        items.push(itemsObject.href);
                    }
                }
            }

            var type = itemResult.base.type;
            var name = itemResult.common.name;

            var text = repeatChar(depth, '\t') + ('folder' === type ? '- (folder) ' : '')+ 'depth: '+depth+' '+name;
            children.push(text);
            //console.log(text);

            if(items.length) {
                for (var j = 0; j < items.length; ++j) {
                    traverse(items[j], depth + 1, children)
                        .then(function() {deferred.resolve(depth);});
                }
            } else {
                deferred.resolve(depth);
            }
        }
    }

    return deferred.promise;
};

var children = [];
traverse(rootItemUrl, 0, children)
                        .then(function toConsole(depth) {
                            // >> Alas I hit this point too early <<
                            console.log(children);
                            console.log('End');
                        });

【问题讨论】:

    标签: node.js recursion promise traversal tree-traversal


    【解决方案1】:

    对于对此问题的答案感兴趣的人,请继续阅读,因为我找到了一个解决方案没有承诺。我完全摆脱了支持回调的承诺。请注意,与原始代码相比,我做了一些更改,例如收集结果而不是在递归代码中将它们打印到标准输出,我删除了一些其他的绒毛。

    var traverse = function(options, rootItemUrl, depth, done) {
        var results = [];
    
        options.path = rootItemUrl;
        https.get(options, onItemResultResponse);
        function onItemResultResponse(itemResultResponse) {
            var body = [];
            itemResultResponse.on('data', function onDataChunk(data) {
                body.push(data);
            });
            itemResultResponse.on('end', onItemResultData);
            itemResultResponse.on('error', onRequestItemsError);
            function onRequestItemsError(e) {
                console.log('Get items failed for <' + rootItemUrl + '>.');
                done(e);
            }
            function onItemResultData() {
                var items = [];
                var itemResult = JSON.parse(Buffer.concat(body).toString());
    
                var embedded = itemResult._embedded;
                results.push(toItemInfo(itemResult, depth));
                var collection = embedded ? embedded['collection'] : undefined;
                var embeddedItems = collection ? collection._embedded : undefined;
                if (embeddedItems) {
                    var itemsObject = embeddedItems['item'];
                    if (itemsObject) {
                        if (itemsObject.length) {
                            for (var i = 0; i < itemsObject.length; ++i) {
                                items.push(itemsObject[i]);
                            }
                        } else {
                            items.push(itemsObject);
                        }
                    }
    
                    var itemInfos = new Array(items.length);
                    for (var iii = 0; iii < items.length; ++iii) {
                        itemInfos[iii] = toItemInfo(items[iii], depth + 1);
                    }
    
                    var ii = 0;
                    (function next() {
                        var nextItemInfo = itemInfos[ii++];
                        if (!nextItemInfo) {
                            return done(null, results);
                        }
                        if ('folder' === nextItemInfo.type) {
                            traverse(options, nextItemInfo, depth + 1, function done(err, result) {
                                results = results.concat(result);
                                next();
                            });
                        } else {
                            results.push(nextItemInfo);
                            next();
                        }
                    })();
                }
            }
        }
    };
    traverse(options, rootItemUrl, 0, function done(e, results) {
       var text = '';
       for(var ii = 0; ii < results.length; ++ii) {
            var itemInfo = results[ii];
            text += repeatChar(itemInfo.depth, '\t') + ('folder' === itemInfo.type ? '- (folder) ' : '') + 'depth: ' + itemInfo.depth + ' ' + itemInfo.name;            
        }
        console.log(text);
        console.log("End");
    });
    

    【讨论】:

      猜你喜欢
      • 2014-10-30
      • 2016-01-06
      • 2016-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-24
      • 2020-07-22
      相关资源
      最近更新 更多