Обещание рекурсивной функции в node.js

Я использую bluebird для потока управления в своем приложении, я пытаюсь реализовать promisify, чтобы расширить мою рекурсивную функцию до обещания, но похоже, что метод "тогда" так и не был выполнен

Я выполняю сопоставление одного объекта JSON с другим, функция поиска рекурсивно просматривает свойства JSON и возвращает свойство на основе определенного условия.

var promise = require("bluebird");
var mapToModel = function(res){
  // res is a json structure
  var processes = res.definitions.process;
  var diagrams = res.definitions.BPMNDiagram; 
  var documents = [];
  for(var prop in processes) {
    if(processes.hasOwnProperty(prop)){
      var propertyNames = Object.getOwnPropertyNames(processes[prop]);
      for(var property in processes[prop]){
        var mapping ={};
        if(property==="$"){
          //do something with the process
        }else{
        //shapes
          mapping.hash = hash.hashCode(new Date().toString());
          mapping.type = property;
          mapping.value = processes[prop][property];
            var bpmnItem = findPromise(processes[prop][property], function(x) {return x.$.id;}).then(function(value){
              //I'm not reaching this point
              var bpmnId = value.$.id;
              console.log(value);
              if(bpmnId!=undefined){
                console.log("return:"+ bpmnId);
              }  
          });

          documents.push(mapping);
        }
      }
    }
     return documents;
  }
}

var findPromise = promise.promisify(find);
function find(items,f) {
    for(var key in items) { 
        var elem = items[key]; 
        if (f(elem)) { return elem;}
        if(typeof elem === "object") { 
            find(elem,f); // call recursively
        }
    }
}

person pedrommuller    schedule 12.05.2014    source источник


Ответы (1)


Метод обещания Bluebird работает на принятом для NodeJS соглашении об обратном вызове — nodebacks.

Nodebacks имеют особый формат someOp(function(err,result){, то есть первый аргумент всегда является ошибкой.

На самом деле ваш метод find даже не является асинхронным, так что нет причин обещать его с самого начала. Вы можете просто назвать это как есть.

Как правило, вы не должны обещать синхронные функции, вы просто вызываете их как обычно. На самом деле, в вашем коде, похоже, нет асинхронной операции, поэтому вам вообще не следует использовать в нем промисы.

Вы можете просто сделать:

mapping.value = processes[prop][property];
var value = find(processes[prop][property], function(x) {return x.$.id;});
var bpmnId = value.$.id;
console.log(value);
if(bpmnId!=undefined){
    console.log("return:"+ bpmnId);
}  

Помните, обещания — это абстракция над конечным результатом. Вы продолжаете делать все синхронно, как и раньше.

person Benjamin Gruenbaum    schedule 12.05.2014
comment
это был мой первый вариант, просто установив значение с помощью функции, которая отлично работала для небольших условий поиска, но когда я попытался с более сложными операциями, я заметил, что в управлении потоком не ждал выполнения функции, поэтому я решил попытаться выполнить обещания - person pedrommuller; 12.05.2014
comment
@Pedro не дождался выполнения функции? JavaScript (если только вы явно не попросите об этом) не имеет понятия вытесняющей многозадачности, проще говоря — весь код выполняется до завершения. Если ваш код не доработался - значит вы сделали что-то асинхронное. Если да, создайте отдельный пример этого (желательно в новом вопросе). В противном случае ваш код мог бы вызвать исключение. Как правило, вы не должны обещать API, которые в любом случае не используют обратные вызовы. - person Benjamin Gruenbaum; 12.05.2014
comment
спасибо за помощь, я создал еще один вопрос с моим другим сценарием, который я описал ранее, любая помощь будет полностью оценена stackoverflow.com/questions/23613036/ - person pedrommuller; 12.05.2014