2017-12-30 49 views
2

내 응용 프로그램에 사용할 데이터 배열을 구축하기 위해 약속을 사용하여 중첩 된 호출이 있습니다.배열 값은 사용할 수 없지만 console.log에 표시됩니다.

첫 번째 호출은 헤더 또는 에피소드 목록을 가져옵니다.

두 번째 호출은 추가 데이터를 얻기 위해 처음 수신 한 에피소드 URL을 사용합니다. 그런 다음 응용 프로그램에서 사용하려는 데이터 배열에 속성을 추가합니다. 다음은 title 및 image_urls [0]입니다.

그런 다음 세 번째 호출은 image_urls [0]을 취해 실제 이미지를 검색하기 위해 호출을 수행합니다. 이제는이 호출에서 console.log 나 두 번째 호출에 추가 된 값을 가진 작업을 수행 할 때 정의되지 않습니다. 그러나 console.log 내 전체 배열에 값이 표시됩니다!

console.log("sections", sections); // show all the data including 2nd call 
console.log("image url", item.url); // This shows 
console.log("image title", item.title); // This doesn't and don't know why 
console.log("image imageurls", item.imageurls); // This doesn't and don't know why 

여기 내 코드

import axios from 'axios'; 

let sections = new Array(), 
    section = null, 
    episodes = null; 

const dataService = 
axios 
    .get('http://feature-code-test.skylark-cms.qa.aws.ostmodern.co.uk:8000/api/sets/coll_e8400ca3aebb4f70baf74a81aefd5a78/items/') 
    .then((response) => { 

    var data = response.data.objects; 

    Promise.all(data.map(function (item) { 
     let type = item.content_type.toLowerCase(); 

     if (type !== "episode") { 
      if (section !== null) { 
       section.episodes = episodes; 
       sections.push(section); 
      } 
      section = new Object(); 
      episodes = new Array(); 
      section.header = item.heading; 
     } 

     if (type === "episode") { 
      var episode = new Object(); 
      episode.url = item.content_url; 
      episodes.push(episode) 
     } 
    })).then(function() { 
     section.episodes = episodes; 
     sections.push(section); 

     Promise.all(sections.map(function (item) { 
      Promise.all(item.episodes.map(function (item) { 
       var url = `http://feature-code-test.skylark-cms.qa.aws.ostmodern.co.uk:8000${item.url}` 
       axios 
        .get(url) 
        .then((response) => { 
        var data = response.data; 

       item.title = data.title; 
       item.imageurls = data.image_urls[0] !== undefined ? data.image_urls[0] : ""; 
      }); 

      })) 
     })).then(function() { 
      Promise.all(sections.map(function (item) { 
       Promise.all(item.episodes.map(function (item) { 
        console.log("sections", sections); 
        console.log("image urr", item.url); 
        console.log("image title", item.title); 
        console.log("image imageurls", item.imageurls); 
       })); 
      })); 
     });; 
    }) 
}) 

export default dataService 
+0

당신은'map()'을 계속 사용하지만 매핑 된 배열에는 아무 것도 반환하지 않습니다. 'Promise.all ([undefined, undefined])'은 쓸모가 없어서 아무것도 기다리지 않습니다. 또한 체인 된'then()'에서 아무 것도 반환하지 않음 – charlietfl

+0

@charlietfl 위의 코드를 수정하는 예제를 보여줄 수 있습니까? – Adam

+0

@charlietfl 내가 매핑하는 배열 나는 약속 안에서 업데이트 중입니다. 세 번째 호출에서 항목 속성을 수행 할 때 섹션 배열을 콘솔에 기록 할 때 값이 나타나는 이유를 설명 할 수 있습니까? – Adam

답변

1

다음은 당신을 위해 일한다, 나는 당신이 약속을 연구지도 및 줄이기 위해 약간의 시간을 보내고있다 생각합니다.

엑시 오스를 제거하고 가져 오기를 사용하여 사이트에서 브라우저에서 테스트 할 수 있으므로 api page을 열고 콘솔에서 코드를 실행하고 (줄 바꿈없이 var를 const로 바꿉니다).

도움이 필요하면 알려주십시오.

const base = "http://feature-code-test.skylark-cms.qa.aws.ostmodern.co.uk:8000"; 
const setEpisodeDetails = episode => 
    fetch(`${base}${episode.url}`) 
    .then(response=>response.json()) 
    .then(
     data => 
     Object.assign(
      {} 
      ,episode 
      ,{ 
      title : data.title, 
      imageurls : data.image_urls[0] || "" 
      } 
     ) 
    ) 
    .then(//fetch image url 
     episode => 
     (episode.imageurls!=="") 
      ? fetch(`${base}${episode.imageurls}`) 
      .then(response=>response.json()) 
      .then(
       imageData=> 
       Object.assign(
        {}, 
        episode, 
        { 
        image_content_url:imageData.url 
        } 
       ) 
      ) 
      : episode 
    ); 
const setAllEpisodeDetails = sections => 
    Promise.all(
    sections.map(
     section => 
      Promise.all(
      section.episodes.map(
       setEpisodeDetails 
      ) 
     ) 
      .then(
      episodes => 
       Object.assign(
       {}, 
       section, 
       {episodes} 
      ) 
     ) 

    ) 
); 
const createSections = data => 
    data.reduce(
    (acc,item)=>{ 
     (item.content_type.toLowerCase()!=="episode") 
     ? acc.push({header:item.heading,episodes:[]}) 
     : acc.slice(-1)[0].episodes.push({url:item.content_url}) 
     return acc 
    }, 
    [] 
); 
const dataService = 
    fetch(`${base}/api/sets/coll_e8400ca3aebb4f70baf74a81aefd5a78/items/`) 
    .then(response=>response.json()) 
    .then(
     response => 
     setAllEpisodeDetails(createSections(response.objects)) 
    ) 
    .then(
     sections => 
      console.log(
      "sections", 
      JSON.stringify(sections,undefined,2) 
     ) || //remove this console log if it works 
      // (can remove the whole last then) 
      //do not remove this it returns sections (unless you get rid of the whole then) 
      sections 
    ); 

//removed export, should log the result when done (or error) 
+0

Ok입니다. 그것의 대부분을 이해하지 못하면 약간의 연구를 할 것입니다.실제 이미지를로드하는 setEpisodeDetails 뒤에 다른 호출을 추가하고 추가합니다. – Adam

+0

@ Adam [이 링크] (http://feature-code-test.skylark-cms.qa.aws.)를 열면 출력이 올바른지 확인할 수 있습니다. ostmodern.co.uk:8000/api/episodes/film_a5e1022dfd874e169fd6da6597d0cd0f/) 현대적인 브라우저에서 (최근 크롬 괜찮겠습니다). F12 키를 누르고 콘솔에서 코드를 붙여 넣습니다. 'dataService.then (result => console.log (JSON.stringify (result, undefined, 2)))' – HMR

+0

예'export default dataService'를 작동하는 것으로 볼 수 있습니다. 내가 episode.imageurls를 사용하여 실제 이미지를 검색하기 위해 setEpisodeDetails 이후에 API 요청을 확장하는 방법을 잘 모르겠다. 보여 주실 수 있어요? – Adam