여러 기능을 기다리겠다고 약속하고 실패한 기능을 다시 시도하십시오.

그래서 매일 여러 타사 API에서 데이터를 가져오는 비동기 함수를 만들어야 하는 상황에 처했습니다. 제 걱정은 타사의 가동 중지 시간을 제어할 수 없다는 것입니다. 그리고 그 (기능)이 자동으로 실행되어 나를 더 혼란스럽게 만듭니다. (글쎄요, 저는 그저 행복하고 조용한 주말을 원합니다(: )

1개의 URL에서 여러 비동기 요청이 있으면 해당 서버에 과부하가 걸릴 수 있습니다. 이러한 일이 발생하면 서버가 다시 시작되고 몇 초(분 또는 그 이상) 동안 오프라인 상태가 되고 모든 요청이 실패하게 됩니다.

모든 웹사이트가 API를 제공하는 것은 아니기 때문에 많은 웹사이트를 크롤링해야 하는 경우가 있습니다. 한 번에 많은 대형 웹사이트를 크롤링하려면 꽤 오랜 시간이 걸릴 수 있습니다. 웹 사이트에 연결해야 하는 시간이 많을수록 요청 시간 초과가 발생할 가능성이 높아집니다. 특히 응용 프로그램의 대역폭이 제한된 경우. 이로 인해 요청 시간이 초과될 수 있습니다.

개발자가 수동으로 요청을 다시 시작하지 않고 애플리케이션이 위의 모든 작업을 자동으로 수행해야 하는 경우 더 복잡합니다.

여기 내 솔루션이 있습니다. 3가지 기능만 필요합니다(4번째 기능은 선택 사항임).
  • URL 배열을 매개변수로 사용하여 Promise All 함수를 호출하는 주요 함수입니다.
  • Promise All 함수, 우리가 Promise.all()를 넣고 모든 약속이 실행된 후 원하는 것을 넣습니다.
  • Axios 함수는 axios.get() 함수를 넣어 타사로부터 요청을 받고 요청이 성공하면 JSON을 반환하고 요청이 실패하면 URL(문자열)을 반환합니다.
  • 지연(다시 요청) 기능, 여기서 n초 지연 후 Promise All 기능을 호출하도록 setTimeout()를 넣습니다. (이 기능은 다음 요청을 지연하려는 경우 선택 사항입니다).

  • 액시오스 함수



    예를 들어, 이 간단한 api 을 사용할 것입니다. JSON으로 예상되는 결과:

    {
      "test": "one",
      "hello": "world"
    }
    

    이 API로 인해 오류(내부 서버)가 발생한다고 가정하고 throw 대신 URL을 반환합니다.

    const axiosFunc: any = (async (url: string) => {
      return await axios.get(url)
        .then(response => response.data)
        .catch(e => url);
    });
    

    모든 기능을 약속


    Promise.all() 약속 배열을 허용합니다. 다음과 같이 작성하는 대신:

    Promise.all([axiosFunc(url1),axiosFunc(url2),...]);
    

    다음과 같이 작성할 수 있습니다.

    const urls = [url1,url2,...];
    Promise.all(urls.map(url => this.axiosFunc(url));
    

    예상 결과는 Axios 함수의 결과 배열, 즉 json 객체(api의 결과) 또는 문자열(url)입니다. 단순 if..else.some() 를 사용하여 결과에 문자열이 있는지 여부를 확인합니다. 문자열이 있으면 .filter() 를 사용하여 유형별로 결과를 분할합니다.

    if(data.some(val => typeof val == 'string')) {
      /** filter failed one by checking its type and execute again */
      const failedReq = data.filter(val => typeof val == 'string');
      this.requestAgain(failedReq);
    
      /** filter success one by checking its type and save its result to db */
      const successReq = data.filter(val => typeof val !== 'string');
      this.saveResult(successReq);
    } else {
      this.saveResult(data);
    }
    

    문자열 1(실패한 1)은 this.requestAgain() 로 이동합니다. 이 게시물의 뒷부분에서 이 기능에 대해 알아보겠습니다. 그리고 문자열이 아닌 것(성공한 것)은 this.saveResult() 로 이동합니다. 이 기능에서 성공적인 결과의 데이터는 데이터베이스 또는 캐시 또는 기타 데이터 저장 방법에 저장됩니다.

    다음은 이 함수의 전체 코드입니다.

    const promiseAllFunc: void = ((urls: string[]) => {
      return await Promise.all(urls.map(url => this.axiosFunc(url))
        .then(data => {
          if(data.some(val => typeof val == 'string')) {
            /** filter failed one by checking its type and execute again */
            const failedReq = data.filter(val => typeof val == 'string');
            this.requestAgain(failedReq);
    
            /** filter success one by checking its type and save its result to db */
            const successReq = data.filter(val => typeof val !== 'string');
            this.saveResult(successReq);
          } else {
            this.saveResult(data);
          }
        })
    });
    

    주요 기능



    url 배열(타사 API)을 매개변수로 사용하여 위에서 Promise All 함수를 호출합니다.

    const main: any = (() => {
      let dummyUrls = [
        'http://echo.jsontest.com/hello/world/test/one',
        'http://echo.jsontest.com/hello/world/test/two',
        'http://echo.jsontest.com/hello/world/test/three'
      ];
      return this.promiseAllFunc(dummyUrls);
    });
    

    지연 기능



    이 기능은 선택 사항입니다. 다음 요청을 지연시키려면 setTimeout() 로 추가 기능을 작성할 수 있습니다. 다음은 다음 요청에 대해 10초 지연이 있는 예입니다.

    const requestAgain: any = ((urls: string[]) => {
      setTimeout(() => {
        this.promiseAllFunc(urls);
      }, 10000);
    });
    

    이 방법은 내 모든 문제를 해결합니다. 자동으로 실행됩니다(Cronjob 사용). 실패한 요청 재시도(Cronjob을 사용하여 지연 기능을 수정할 수도 있음).

    그렇군요, 감사합니다 :)
    의견 섹션에 의견을 자유롭게 추가하십시오. 이것은 내 첫 번째 게시물입니다. 여기 저기에 문법 실수가 있을 수 있지만 (또는 그 이상 :D ), 여전히 이해할 수 있다고 생각합니다.

    좋은 웹페이지 즐겨찾기