2016-06-24 4 views
0

Я пытаюсь пройти через кучу ресурсов HAL/JSON, которые моделируют дерево элементов, связанных через hrefs и извлекаемых через https. То есть «элементом» может быть отпуск или другая ветка с другими листьями. Увы, я не могу понять. Обход всегда будет завершен, т. Е. Ударит обратный вызов then() в последнем примере моего примера кода, прежде чем будет выполнена полная рекурсия. По сути, я получаю только первый слой назад у детей.Async HTTP (S) Обход только с использованием Node.js Promisses

Мой вопрос: что я пропустил, чтобы понять это правильно?

Я все еще изучаю Nodejs, но я успешно использовал обещания в более ранних примерах. Я задаю этот вопрос здесь, потому что я обязан использовать только модуль 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'); 
         }); 

ответ

0

Для того, чтобы тот, кто заинтересован в ответ на это, пожалуйста, продолжайте читать, потому что я нашел решение без обещаний. Я полностью избавился от обещаний в пользу обратных вызовов. Обратите внимание, что я внес некоторые изменения в сравнении с исходным кодом, например. собирать результаты, а не печатать их на stdout в рекурсивном коде, и я удалил другой пух.

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"); 
}); 
Смежные вопросы