2017-11-23 3 views
0

우리 프로그램에서는 await으로 작업 재시도 패턴을 구현하려고합니다.기다려온 비동기 메소드 이전 재시도 페이로드 유지

우리의 주요한 문제는 우리의 방법이 후속 시도에서 첫 번째 재시도 페이로드를 유지한다는 것입니다.

async retryTaskUntilExpectedValue({ 
    task, 
    expectedValue, 
    messageOnError = 'Max retry number reached without expected result', 
    maxRetries = 10, 
    timeout = 10, 
    spinner = null 
    }) { 
    let printFn = console.log; 
    if (spinner !== null) { 
     printFn = spinner.text; 
    } 

    // Proceed retries 
    for (let i = 1; i <= maxRetries; i++) { 
     try { 
     let result = await task; 

     console.log(result); // Always display same result: {"state": "upgrading"} even if curling returns {"state": "upgraded"} after about 2 retries 

     result = JSON.parse(result).state; 

     if (result === expectedValue) { 
      return Promise.resolve(result); 
     } else if (i <= maxRetries) { 
      printFn(`Result "${result}" differs from expected value "${expectedValue}"`); 
      await wait(1000); 

      printFn(`Waiting ${timeout}s before retry`); 
      await wait(timeout * 1000); 

      printFn(`Retrying (${i})`); 
      continue; 
     } else { 
      return Promise.reject(`ERROR: ${messageOnError}`); 
     } 
     } catch (err) { 
     return Promise.reject(`ERROR: Unexpected error while running task`); 
     } 
    } 
}; 

그리고 우리의 CLI에서 사용 : 여기

가 재시도 방법 우리의 경우

checkUpgrade(url) { 
    return retryTaskUntilExpectedValue({ 
     task: this.makeHttpRequest('GET', url), 
     expectedValue: 'upgraded' 
    }); 
} 

작업이 우리의 백엔드 데이터베이스에서 상태를 반환하는 HTTP 요청입니다.

모델은 간단합니다 : { "state": "upgrading" } 그런 다음 백엔드 작업이 완료되면 { "state": "upgraded"}을 반환합니다.

작업을 처리하는 데 약간의 시간이 걸립니다 (약 20 초). 우리의 테스트에서이 문제가 발생했습니다

  • 먼저 전화 : upgrading
  • 첫 번째 재시도 : 그 후 upgrading
  • 을 손으로 직접 REST API를 컬링에 의해, 나는 upgraded status
  • 다른 모든 시도를 얻을 수 CLI를에 : 그래서 우리가 구축 CLI에서 upgrading

, 우리는 10 시간 결과를 가지고 : Result "upgrading" differs from expected value "upgraded"

이후 재 시도에서 let response = await task;이 재 시도 할 때마다 작업 메서드를 호출하지 않는 것 같습니다. 실제로 실제 전화가 걸려온다면, 우리가 컬을 통해 얻을 수 있기 때문에 업그레이드 된 상태를 확실히 검색 할 수 있습니다.

실제로 await task;을 호출 작업 메서드를 트리거하고 첫 번째 호출에서 결과를 유지하지 않으려면 어떻게해야합니까?

+0

'task'가 약속이라면, 한번만 해결하거나 거절 할 것이며, 이후에'await'는 첫 번째 해결이나 거절을 참조 할 것입니다. –

+2

"*'let response = await task;처럼 보입니다. 이후 재시도에서 재 시도 할 때마다 작업 메소드를 호출하지 않습니다. *"- 물론 아닙니다. 'task'는 메소드가 아니며, 약속이고, 그것들은 단일 값으로 한 번만 해결됩니다. 대신에 함수를 전달하고'task()'를 사용하여 함수를 호출하면됩니다. – Bergi

+0

Bergi에게 감사드립니다. 처음에는 그것을 얻지 못했습니다. 나는 지금 더 잘 이해한다. – BlackHoleGalaxy

답변

2

약속은 이미 시작한 작업에 대한 결과는 입니다. 내부에 약속으로 task을 전달하면 항상 동일한 결과를 기다리고 동일한 값을 반환합니다.

대신, retryTaskUntilExpectedValue는 약속에 대한 기능을 가지고 그의 호출을 기다리고해야합니다

let result = await functionReturningTask(); 

functionReturningTask 당신이 처음에 task을 얻기 위해 사용 무엇이다.

+0

안녕하세요 Benjamin. 귀하의 답변을 주셔서 감사합니다, 작업은 실제로 약속을 반환합니다. 우리의 makeHttpRequest는 약속을 반환하는 http 노드 요청을 처리하는 간단한 래퍼입니다.그래서 나는 '당신이'처음으로 '일자리'를 얻기 위해 무엇을 사용하던간에 그 부분을 정말로 이해하지 못합니다. ' – BlackHoleGalaxy

+0

retryTaskUntilExpectedValue 메소드에 변수를 추가하려고 시도했습니다 :'let getTask =() => task; '그런 다음 더 좋은 결과를 얻지 않고'await getTask();'를 통해 그것을 사용하십시오. – BlackHoleGalaxy

+3

@BlackHoleGalaxy'() => this.makeHttpRequest ('GET', url)'을 전달해야합니다! – Bergi

관련 문제