Рекурсивная прогулка по дереву с обещанием ES6

Я хочу пройтись по дереву объектов неизвестной глубины и вернуть заданный узел через обещание ES6. (использовал lodash здесь, очевидно, это не обязательно, я понимаю). У меня обход дерева работает нормально, но я немного не понимаю, какой правильный метод гарантирует, что переменная области видимости верхнего уровня promise будет передана в рекурсивные вызовы функций, чтобы она была доступна при вызове .resolve( data ). Прямо сейчас он пытается выполниться при успешном поиске, но не может разрешить промис, поскольку рекурсивная функция перезаписана новым промисом, и ей не удается поднять цепочку:

  deepFindReturn (object, searchKey, searchVal, cb) {
    if ( !cb ) cb = _.noop;
    for(let x in object){
      if (object.hasOwnProperty(x)) {
        if ( object[searchKey] === searchVal ) {
          return cb( object );
        }
        if ( _.isArray( object[x] ) && !this.found ){
          object[x].forEach( (item) => {
            this.deepFindReturn(item, searchKey, searchVal, cb);
          });
        } else if ( typeof object[x] === typeof {}  && !this.found ) {
          this.deepFindReturn(object[x], searchKey, searchVal, cb);
        }
      }
    }
  }

  deepFindReturn(data, 'uuid', 'f8d1ffed-9b51-4982-97b7-60f8e074eda4')

вот дерево, по которому я иду, если это поможет:

  data = {
     "name":"root",
     "created":"2015-04-07T20:36:29.711Z",
     "createdBy":"admin",
     "uuid":"9731cedc-8ed7-4367-b95d-30898c7913a1",
     "primaryType":"folder",
     "path":"/root",
     "itemCount":7,
     "items":[
        {
           "name":"219760_964977275754_1803638_o.jpg",
           "baseVersion":"afe1994e-d9a8-47fd-a7db-dcf0e085fc05",
           "created":"2015-06-01T13:30:16.490Z",
           "lastModified":"2015-06-01T13:30:16.490Z",
           "isCheckedOut":true,
           "createdBy":"admin",
           "versionHistory":"152eb76a-e0ac-446d-a7e8-47b5e5c821ed",
           "primaryType":"file",
           "lastModifiedBy":"admin",
           "uuid":"25cc6435-6432-47f3-8dc3-f94f2788f2ef",
           "parent":"9731cedc-8ed7-4367-b95d-30898c7913a1",
           "mimeType":"image/jpeg",
           "size":116285
        },
        {
           "name":"Child1",
           "created":"2015-04-07T21:03:41.729Z",
           "createdBy":"admin",
           "primaryType":"folder",
           "uuid":"f8d1ffed-9b51-4982-97b7-60f8e074eda4",
           "parent":"9731cedc-8ed7-4367-b95d-30898c7913a1",
           "itemCount":36
        },
        {
           "name":"Child2",
           "created":"2015-04-07T21:14:47.950Z",
           "createdBy":"admin",
           "uuid":"8f1246ff-5053-411a-88de-c465027b998d",
           "primaryType":"folder",
           "parent":"9731cedc-8ed7-4367-b95d-30898c7913a1",
           "itemCount":3
        },
        {
           "name":"Child3",
           "created":"2015-05-01T00:46:36.973Z",
           "createdBy":"admin",
           "uuid":"54f897a4-ac16-4585-83cb-d0e67ca73a74",
           "primaryType":"folder",
           "parent":"9731cedc-8ed7-4367-b95d-30898c7913a1",
           "itemCount":1
        },
        {
           "name":"Child4",
           "created":"2015-05-26T18:18:33.159Z",
           "createdBy":"admin",
           "primaryType":"folder",
           "uuid":"ad1344a9-08b7-44bb-b47d-0efb99c59ac3",
           "parent":"9731cedc-8ed7-4367-b95d-30898c7913a1",
           "itemCount":0
        },
        {
           "name":"Child5",
           "created":"2015-06-07T03:57:20.494Z",
           "createdBy":"admin",
           "primaryType":"folder",
           "uuid":"2b46d7e4-b50e-4eec-b97a-c46b2016926c",
           "parent":"9731cedc-8ed7-4367-b95d-30898c7913a1",
           "itemCount":0
        },
        {
           "name":"content.jpg",
           "baseVersion":"620c8448-3e51-4a27-b630-60c1272c19da",
           "created":"2015-06-03T15:09:25.192Z",
           "lastModified":"2015-06-03T15:09:25.193Z",
           "isCheckedOut":true,
           "createdBy":"admin",
           "versionHistory":"871afa2a-5a2c-4762-bc26-a69022234850",
           "primaryType":"file",
           "lastModifiedBy":"admin",
           "uuid":"c8c63420-b525-4b36-bce3-a7c4cc55c07a",
           "parent":"9731cedc-8ed7-4367-b95d-30898c7913a1",
           "mimeType":"image/jpeg",
           "size":30711
        }
     ]
  }

person Brian    schedule 10.06.2015    source источник
comment
скорее упражнение в понимании, чем что-либо еще, у меня это уже работает без обещаний. Я понимаю вашу точку зрения, это невозможно сделать с обещаниями, так что это бесполезный эксперимент.   -  person Bergi    schedule 11.06.2015
comment
Можете ли вы показать версию без обещаний, пожалуйста?   -  person Brian    schedule 11.06.2015
comment
Вы просто удаляете строку _1_ и заменяете строку _2_ на _3_. Довольно просто.   -  person Bergi    schedule 11.06.2015
comment
Э-э, это не похоже на работу, потому что для этого также потребуется const promise = Promise.resolve() для рекурсивных вызовов (в ваших терминах не удается поднять цепочку). Или вся цель этой функции - установить для свойства promise.resolve( object ) значение return object?   -  person Brian    schedule 11.06.2015
comment
Действительно, ты прав. Я заставлю это работать, а затем обновлю.   -  person Bergi    schedule 11.06.2015
comment
А, обратный звонок. Ожидаете ли вы, возможно, несколько совпадений?   -  person Brian    schedule 11.06.2015
comment
Не в этом случае, мой вариант использования - поиск по UUID   -  person Bergi    schedule 11.06.2015
comment
Текущая демонстрация   -  person Brian    schedule 11.06.2015


Ответы (1)


Я бы переместил большую часть логики в другую функцию и обернул эту функцию в Promise. Я не уверен, что есть какая-то польза от рекурсивного создания обещаний для каждой ветви дерева. Функция не блокируется, с минимальными изменениями в логике.

function deepFindReturn (object, searchKey, searchVal) {
  function doer(object, searchKey, searchVal) {
    if ( object[searchKey] === searchVal ) {
      return object;
    }

    for(let x in object) {
      let val = object[x];

      if (typeof val === typeof searchVal) {
        continue;
      }

      if ( Array.isArray( val ) ) {
        for (let item of val) {
          let o = doer(item, searchKey, searchVal);
          if (o) {
            return o;
          }
        }
      }
      else if ( typeof val === 'object' ) {
        let o = doer(val, searchKey, searchVal);
        if (o) {
          return o;
        }
      }
    }
  };

  return new Promise(function(resolve) {
    resolve(doer(object, searchKey, searchVal));
  });
}

deepFindReturn(data, 'uuid', 'f8d1ffed-9b51-4982-97b7-60f8e074eda4')
  .then((o) => { console.log(o); });

Если же целью упражнения было поэкспериментировать с рекурсивным асинхронным кодом, я бы посмотрел на Async Вместо обещаний. Гораздо удобнее использовать в рекурсивных ситуациях.

Я думаю, что единственный способ сделать это с промисами - это генерировать Promise для каждой итерации и добавлять их в новый массив. Вы должны передать этот новый массив в Promise.race. . Что-то типа:

а) обещание не может быть Promised извне б) WTH вы используете обещания здесь, когда вы ничего не делаете асинхронно?!

Promise.race(val.map(function(item) {
  return new Promise(function(resolve) {
    // Determine result
    resolve(result);
  });
}))
  .then((result) => { /* Deal with result */ });
person kim3er    schedule 12.06.2015