如何链接多个observable减少角度4以生成base64图像

时间:2017-10-12 18:51:32

标签: angular rxjs observable rxjs5

我有多个父对象,每个对象都有多个子对象,每个子对象都有多个链接。我想查看所有子项链接,删除没有实时链接的子项,并删除已删除所有子项的父项。

我正在尝试了解如何使用角度4中的Rx编写以下代码:

parents.reduce((updatedParents, parent) => {
 parent.children = parent.children.reduce((updatedChildern, child) => {
   child.links = child.links.reduce((updatedLinks, link) => {  
     if (link is live) updatedLinks.push(link) // asnyc operation
     return updatedLinks;
   },[]);
   if (child.links.length) updatedChildren.push(child);
 },[]);
 if (parent.children.length) updatedParents.push(parent); 
},[])

我可以想象如何使用promises做到这一点,并使用bluebird承诺all / promise.reduce等,但是我如何使用Observable实现这个并减少等?我真的很困惑,我不知道该怎么做。我尝试了几种方法,无法让它发挥作用。我希望单个事件能够将过滤后的结果返回给我,就像承诺一样。

欢迎任何建议。

这是结构:

const parents = [
  {
    children: [
      {
        links: [
          'http://www.onelink.com', 'http://www.secondlink'
        ]
      },
      {
        links: [
          'http://www.threelink.com', 'http://www.fourlink'
        ]
      }
    ]
  },
  {
    children: [
      {
        links: [
          'http://www.fivelink.com', 'http://www.sixlink'
        ]
      },
      {
        links: [
          'http://www.sevenlink.com', 'http://www.egihtlink'
        ]
      }
    ]
  }

这是我走了多远。

return Observable.from(parents)
      .flatMap(parent => Observable.from(parent.children)
        .flatMap(child => Observable.from(child.images)
          .reduce((updatedImages, imgSrc, idx) => {
            return this.http.get(imgSrc)
              .map(res => {
                if (res.status === 200) {
                  updatesImages.push(base64Ecode(imgSrc));
                }
                console.log(res);
                console.log(updatedImages);
                return updatedImages;
              });
          })
        .filter(p => p.length !== 0)
      )
      .filter(c => c.length !== 0)

2 个答案:

答案 0 :(得分:0)

你可以尝试使用filter而不是reduce,因为reduce更多是用于压缩数据而不是基于过滤器删除。

可能有更好的方法从角度ping而不是仅仅抓住整个页面,但想法是一样的。

const parents = [
  [
    [
      "http://www.onelink.com",
      "http://www.secondlink"
    ],
    [
      "http://www.threelink.com",
      "http://www.fourlink"
    ]
  ],
  [
    [
      "http://www.fivelink.com', 'http://www.sixlink"
    ],
    [
      "http://www.sevenlink.com",
      "http://www.egihtlink"
    ]
  ]
];


function getLiveLinks() {
  parents.filter((child) => {
    return child.filter((link) => {
      console.log(link)
      http.get(link).toPromise().then((res)=>{
          live = res;
          //check if resolved and return if true
      });
      
    }).length > 0;
  });
}

答案 1 :(得分:0)

这很棘手,因为起始结构是不可观察的。 在我看来,最好首先解决所有链接,然后使用不可观察缩减的变体。

// simulated http.get
const http = { get: link => Rx.Observable.of([link, link.endsWith('.com')])}     

// non-observable flatMap
const flatMap = (a, cb) => [].concat(...a.map(cb))
const links = flatMap(parents, x => flatMap(x.children, y => y.links))
console.log(links)

// Rx version of Promise.all()
const linkTests$  = Rx.Observable.forkJoin(links.map(link => http.get(link)))

linkTests$.subscribe(linkTests => {
  const isLive = link => linkTests.some(linkTest => linkTest[0] === link && !!linkTest[1])
  const liveLinks = links => links.filter(link => isLive(link))
  const liveChildren = children => children.filter(child => {
    child.links = liveLinks(child.links)
    return child.links.length
  })
  const liveParents = parents => parents.filter(parent => {
    parent.children = liveChildren(parent.children)
    return parent.children.length
  })

  console.log(liveParents(parents))  
})

工作示例:CodePen