Nice programing

API 요청 시간 초과를 가져 오시겠습니까?

nicepro 2020. 12. 9. 21:47
반응형

API 요청 시간 초과를 가져 오시겠습니까?


나는이 fetch-api POST요청을 :

   fetch(url, {
      method: 'POST',
      body: formData,
      credentials: 'include'
    })

이에 대한 기본 제한 시간이 무엇인지 알고 싶습니다. 3 초 또는 무한 초와 같은 특정 값으로 어떻게 설정할 수 있습니까?


지정된 기본값이 없습니다. 사양 은 시간 초과에 대해 전혀 논의하지 않습니다.

일반적으로 프라 미스에 대한 자체 시간 초과 래퍼를 구현할 수 있습니다.

// Rough implementation. Untested.
function timeout(ms, promise) {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      reject(new Error("timeout"))
    }, ms)
    promise.then(resolve, reject)
  })
}

timeout(1000, fetch('/hello')).then(function(response) {
  // process response
}).catch(function(error) {
  // might be a timeout error
})

설명한 바와 같이 https://github.com/github/fetch/issues/175 하여 설명 https://github.com/mislav


Promise.race를 사용 하는이 요점 의 깔끔한 접근 방식을 정말 좋아합니다.

fetchWithTimeout.js

export default function (url, options, timeout = 7000) {
    return Promise.race([
        fetch(url, options),
        new Promise((_, reject) =>
            setTimeout(() => reject(new Error('timeout')), timeout)
        )
    ]);
}

main.js

import fetch from './fetchWithTimeout'

// call as usual or with timeout as 3rd argument

fetch('http://google.com', options, 5000) // throw after max 5 seconds timeout error
.then((result) => {
    // handle result
})
.catch((e) => {
    // handle errors and timeout error
})

중단 구문을 사용하면 다음을 수행 할 수 있습니다.

const controller = new AbortController();
const signal = controller.signal;

const fetchPromise = fetch(url, {signal});

// 5 second timeout:
const timeoutId = setTimeout(() => controller.abort(), 5000);


fetchPromise.then(response => {
  // completed request before timeout fired

  // If you only wanted to timeout the request, not the response, add:
  // clearTimeout(timeoutId);
})

MDN의 AbortController 페이지를 참조하십시오 .


Fetch API에는 아직 시간 초과 지원이 없습니다. 그러나 그것은 약속으로 포장함으로써 달성 될 수 있습니다.

예를 들어.

  function fetchWrapper(url, options, timeout) {
    return new Promise((resolve, reject) => {
      fetch(url, options).then(resolve, reject);

      if (timeout) {
        const e = new Error("Connection timed out");
        setTimeout(reject, timeout, e);
      }
    });
  }

편집 : 가져 오기 요청은 여전히 ​​백그라운드에서 실행되며 콘솔에 오류를 기록 할 가능성이 높습니다.

실제로 Promise.race 접근 방식이 더 좋습니다.

참조 Promise.race ()는 이 링크를 참조하십시오.

레이스는 모든 약속이 동시에 실행되고 약속 중 하나가 값을 반환하는 즉시 레이스가 중지됨을 의미합니다. 따라서 하나의 값만 반환 됩니다. 가져 오기 시간이 초과되면 호출 할 함수를 전달할 수도 있습니다.

fetchWithTimeout(url, {
  method: 'POST',
  body: formData,
  credentials: 'include',
}, 5000, () => { /* do stuff here */ });

이것이 관심을 끄는 경우 가능한 구현은 다음과 같습니다.

function fetchWithTimeout(url, options, delay, onTimeout) {
   const timer = new Promise((resolve) => {
      setTimeout(resolve, delay, {
      timeout: true,
     });
   });
   return Promise.race([
      fetch(path, request),
      timer
   ]).then(response) {
      if (response.timeout) { 
        onTimeout();
      }
      return response;
   }
}

timeoutPromise 래퍼를 만들 수 있습니다.

function timeoutPromise(timeout, err, promise) {
  return new Promise(function(resolve,reject) {
    promise.then(resolve,reject);
    setTimeout(reject.bind(null,err), timeout);
  });
}

그런 다음 약속을 래핑 할 수 있습니다.

timeoutPromise(100, new Error('Timed Out!'), fetch(...))
  .then(...)
  .catch(...)  

It won't actually cancel an underlying connection but will allow you to timeout a promise.
Reference


  fetchTimeout (url,options,timeout=3000) {
    return new Promise( (resolve, reject) => {
      fetch(url, options)
      .then(resolve,reject)
      setTimeout(reject,timeout);
    })
  }

Building on Endless' excellent answer, I created a helpful utility function.

const fetchTimeout = (url, ms, { signal, ...options } = {}) => {
    const controller = new AbortController();
    const promise = fetch(url, { signal: controller.signal, ...options });
    if (signal) signal.addEventListener("abort", () => controller.abort());
    const timeout = setTimeout(() => controller.abort(), ms);
    return promise.finally(() => clearTimeout(timeout));
};
  1. If the timeout is reached before the resource is fetched then the fetch is aborted.
  2. If the resource is fetched before the timeout is reached then the timeout is cleared.
  3. If the input signal is aborted then the fetch is aborted and the timeout is cleared.
const controller = new AbortController();

document.querySelector("button.cancel").addEventListener("click", () => controller.abort());

fetchTimeout("example.json", 5000, { signal: controller.signal })
    .then(response => response.json())
    .then(console.log)
    .catch(error => {
        if (error.name === "AbortError") {
            // fetch aborted either due to timeout or due to user clicking the cancel button
        } else {
            // network error or json parsing error
        }
    });

Hope that helps.

참고URL : https://stackoverflow.com/questions/46946380/fetch-api-request-timeout

반응형