docs: function rxs(dyn, obj, urlArr, selector, tailArr, limit) {
    // console.log('reporting')
    return new Promise(function(dresolve, dreject) {
  
      // call xs() on all the urlArr, returns promise from grab()
      xs(dyn, urlArr, selector, limit)
        .then(function(grabbed) {
          // set child as result from grab()
          obj.child = grabbed
            // console.log('grabbed', grabbed, obj.child)
  
          var promises = []
            // recursive part on each child
          _.map(obj.child, function(o) {
            // console.log("obj child", o)
            var deferG = new Promise(function(resolve, reject) {
  
              // if x's is callable
              var expectGChild = !_.isEmpty(_.compact(tailArr)) && !_.isEmpty(_.compact(o.hrefs))
                // console.log('expectGChild', expectGChild)
              if (expectGChild) {
                var hrefs = o.hrefs
                var newTailArr = _.clone(tailArr)
                var newSelector = newTailArr.shift()
  
                // recursive call
                rxs(dyn, o, hrefs, newSelector, newTailArr, limit)
                  .then(resolve)
                  .catch(reject)
              } else {
                resolve()
              }
            })
            promises.push(deferG)
            return deferG
          })
  
          // resolve promise for all child
          return Promise.all(promises)
            .then(function(res) {
              // console.log('res',res)
              // attach obj to the highest defer, bubble up
              return dresolve(obj)
            })
            .catch(dreject)
        })
    })
  }