2017-10-23 4 views
1

현재 자바 스크립트에서 비동기 호출 쌍을 생성하려고하고 있지만 올바른 순서로 가져올 수 없습니다.약속을 사용하여 데이터 집합 생성

generateDataPoints: function (iterable, source, arg) { 
    let pairs = [] 
    let prevTime = 0 
    for (let index in iterable) { 
    let event = iterable[index] 
    getTime(event.valueOf()).then(function (time) { 
     query(source[arg], event.valueOf()).then(function(val) { 
     if (time !== prevTime) { 
      prevTime = time 
      pairs.push([time, val]) 
      console.log(pairs) // This works as expected but only happens after the program returns 
     } else { 
      Promise.resolve() 
     } 
     }) 
    }) 
    } 
    return Promise.resolve(pairs) 
} 

문제는 내가 돌아 오면 "pairs.push .."명령이 실행된다는 것입니다. 정확하게 무엇이 잘못되었는지, 어떻게이 프로세스를 동기화 할 수 있는지 파악할 수 없습니다. 어떤 도움을 주셔서 감사합니다.

+0

... 어 ... 코드에 확실하게 약속을 넣었지만 약속 한 내용이 반환되지 않으면 반환되지 않습니다. 작업이 완료 될 때까지 해결하십시오. –

+0

@KevinB 흠, 새로운 약속에서 for 루프를 래핑하려고했지만 "해결 (쌍)"을 반환했습니다. 그것도 작동하지 않았다 – WhosSu

+0

당신은'Promise.all'을 찾고 있습니다. 루프를 사용하여 각각의 개별 결과에 대해 하나의 약속 배열을 만듭니다. – Bergi

답변

0

동기식 코드 (예 : for 루프)를 비동기 코드와 혼합합니다.

function generateDataPoints(iterable, source, arg) { 
    let prevTime = 0 
    [...iterable].reduce((promiseChain, event) => { 
    let pairs; 
    return promiseChain 
     .then(p => { 
     pairs = p; 
     return Promise.all([ 
      getTime(event.valueOf()), 
      query(source[arg], event.valueOf()) 
     ]) 
     }) 
     .then(([time, val]) => { 
     if (time !== prevTime) { 
      prevTime = time 
      return pairs.concat([[time, val]]); 
     } else { 
      return pairs; 
     } 
     }); 
    }) 
    }, Promise.resolve([])); 
} 

이 결국 모든 쌍을 포함 순차적 약속 체인에 iterable을 감소 : 이런 식으로 뭔가를 시도하십시오. 사용자 환경이 가능하게되는 경우

, 당신은 또한 비동기 기능에 몇 가지 변화와 기능을 변환 할 수 있습니다 :

generateDataPoints: async function (iterable, source, arg) { 
    let pairs = [] 
    let prevTime = 0 
    for (let index in iterable) { 
    let event = iterable[index] 
    const [time, val] = await Promise.all([ 
     getTime(event.valueOf()), 
     query(source[arg], event.valueOf()) 
    ]); 
    if (time !== prevTime) { 
     prevTime = time 
     pairs.push([time, val]) 
    } 
    } 
    return pairs; 
} 

편집 :

을 자세히 살펴보면, 그것은하지 않습니다 당신이이 약속들을 순차화할 필요가있는 것처럼 보입니다. 다음과 같이 병렬로 실행할 수 있습니다 :

function generateDataPoints(iterable, source, arg) { 
    Promise.all(
    [...iterable].map(event => Promise.all([ 
     getTime(event.valueOf()), 
     query(source[arg], event.valueOf()) 
    ]) 
).then(pairs => { 
    let prevTime = 0 
    return pairs.filter(([time, val]) => { 
     if (time !== prevTime) { 
     prevTime = time; 
     return true; 
     } else { 
     return false; 
     } 
    }); 
    }); 
} 
+0

태그에 따라 Bluebird도 사용하고 있습니다. 즉, 물건을 더 쉽게 만드는'Promise.map'과 같은 맛있는 음식이 있다는 뜻입니다. – Jacob

+0

그래서 저는 여러분이 작성한 세 번째 것을 구현했습니다. 여기에 문제가 있습니다. 나는 다른 곳에서 호출 된 generateDataPoints를 가지고 함수 x를 호출 할 수있다. X는 매핑이 완료된 후에 쌍 목록을 얻지 만 필터링 프로세스는 시작되지 않았습니다. 왜 이런거야? – WhosSu

+0

이것은 현재 https://pastebin.com/shukspGj로 보입니다. – WhosSu

관련 문제