2017-10-12 30 views
2

我有多个父对象,每个都有多个子对象,每个子对象都有多个链接。我想检查所有的儿童链接,删除没有实时链接的儿童,并删除所有孩子已被删除的父母。如何链接多个可观察的减少角度4以生成base64图像

我想做了解如何编写角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); 
},[]) 

我能想象如何做到这一点使用的承诺,并承诺所有/ 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) 
+0

updateLinks是obervable? RXjs有一个reduce操作符,但它用在observable上,而不是通过数组reduce发送observable。 – rjustin

+0

目前还不清楚你在问什么。输入数据很好理解。您试图实现的数据转换是什么,以及可能需要的副作用是什么? –

+0

@Dory Zidon你的意思是你只是想对孩子的所有链接执行异步操作(如果有的话)? – CozyAzure

回答

0

您可以尝试使用过滤器而不是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; 
 
    }); 
 
}

+0

整个想法是让它在一个角度4的项目中工作,没有异步等待,这些是许多浏览器不支持的新功能... –

+0

@DoryZidon This可以很容易地被一个承诺取代,主要想法是使用过滤器而不是减少。 – rjustin

+0

我可能会建议你尝试一下测试。看起来你的'link'实际上是链接数组。 –

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

+0

雅,但然后你必须重新运行整个事情两次..理想不需要以某种方式.. –

+0

两次?我不明白。 –

+0

如果你的意思是提取链接后扫描树是两个循环,你几乎不会注意到这种差异,因为主要时间成本是http.get。 –