2017-10-12 31 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。 –