request.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import fetch from 'dva/fetch';
  2. function parseJSON(response) {
  3. return response.json();
  4. }
  5. function checkStatus(response) {
  6. if (response && (response.status >= 200 && response.status < 300)) {
  7. return response;
  8. }
  9. const error = new Error(response ? response.statusText : 'Error Fetch');
  10. error.response = response;
  11. throw error;
  12. }
  13. /**
  14. * Requests a URL, returning a promise.
  15. *
  16. * @param {string} url The URL we want to request
  17. * @param {object} [options] The options we want to pass to "fetch"
  18. * @return {object} An object containing either "data" or "err"
  19. */
  20. class TimeoutError extends Error {
  21. constructor(message) {
  22. super(message);
  23. this.name = 'TimeoutError';
  24. }
  25. }
  26. /**
  27. * 提供参数校验和wrapper功能
  28. *
  29. * @param {*} url
  30. * @param {*} [options={ method: 'GET' }]
  31. * @returns {Promise} the request result
  32. */
  33. export default function request(url, options, timeout) {
  34. let retryCount = 0;
  35. class Request {
  36. constructor(url, {
  37. retry,
  38. ...options
  39. }) {
  40. this.url = url;
  41. this.retry = retry || 0;
  42. this.timeout = timeout || 8 * 1000;
  43. this.options = options;
  44. }
  45. then(fn) {
  46. let done = false;
  47. setTimeout(() => {
  48. // 无论是请求重试还是最终超时错误,此次请求得到的结果作废
  49. if (retryCount < this.retry && !done) {
  50. done = true;
  51. retryCount++;
  52. this.then(fn);
  53. } else {
  54. let error = new TimeoutError(`timeout of ${this.timeout}ms execeeded`);
  55. this.catchError(error);
  56. }
  57. }, this.timeout);
  58. fetch(this.url, this.options)
  59. .then(checkStatus)
  60. .then(parseJSON)
  61. .then(data => {
  62. // 未进入重试或者超时错误,返回结果
  63. if (!done) {
  64. fn({
  65. data
  66. });
  67. done = true;
  68. }
  69. })
  70. .catch(err => {
  71. this.catchError(err);
  72. });
  73. return this;
  74. }
  75. catch (fn) {
  76. this.catchError = fn;
  77. }
  78. }
  79. return new Promise((resolve, reject) =>
  80. new Request(url, options).then(res => resolve(res)).catch(err => reject(err))
  81. );
  82. }