异步/等待获取的ES7超时

时间:2016-06-08 13:45:40

标签: javascript timeout async-await fetch-api ecmascript-next

我想在fetch方法中设置超时,然后我关注this github issue

@mislav回答,我们可以自定义超时方法,如下所示。

// 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
})

并改进了@nodkz

function timeoutPromise(ms, promise) {
  return new Promise((resolve, reject) => {
    const timeoutId = setTimeout(() => {
      reject(new Error("promise timeout"))
    }, ms);
    promise.then(
      (res) => {
        clearTimeout(timeoutId);
        resolve(res);
      },
      (err) => {
        clearTimeout(timeoutId);
        reject(err);
      }
    );
  })
}

但我想在ES7 async / await语法中调用该方法,我尝试以下方法但失败了。

async request() {
  try { 
    let res = await timeout(1000, fetch('/hello'));
  } catch(error) {
    // might be a timeout error
  }
}

如何在ES7 async / await语法中使用它?

谢谢你的时间。

更新

感谢@Bergi回复,并在http请求步骤中显示我的代码。

ES7提取

'use strict';

import { configApi, } from 'tyrantdb-config';
import { timeoutPromise, } from 'xd-utils-kit';

const keyResponse = configApi.keyResponse;
const KEY_DATA = keyResponse.data;


module.exports = {
  async fetchLogin(url, params, dataRely) {
    let {
      self, processor, route,
      storage, isLocalStoraged,
      email, password, _warning, } = dataRely;

    self.setState({ isWait: true, });

    try {
      let res = await timeoutPromise(10, fetch(url, params));
      if (res.status >= 200 && res.status < 300) {

        let resJson = await res.json();
        let resData = resJson[KEY_DATA];

        let cache = {
          ...resData,
          password,
        };
        if (isLocalStoraged !== true) {
          processor(cache, storage);
        }
        global.g_user = cache;
        self.setState({ isWait: false, });

        // clean user info which already bind to self[this]
        self.email = self.password = null;
        self.isLocalStoraged = false;
        route();

      } else {
        console.log(`[login] response code: ${res.status}`);
        self.setState({ isWait: false, });
        _warning();
      }
    } catch(error) {
      console.error(error);
    }
  },

  saveLoginState: (cache, storage) => {
    storage.save({
      key: 'loginState',
      rawData: cache,
    });
  },

  openURL: (url, Linking) => {
    Linking.canOpenURL(url).then(supported => {
      if (!supported) {
        console.log(`can\'t handle url: ${url}`);
      } else {
        return Linking.openURL(url);
      }
    }).catch((err) => {
      console.log(`error occurred: ${err}`);
    })
  },
};

ES6 fetch

'use strict';

import { configApi, } from 'tyrantdb-config';
import { timeoutPromise, } from 'xd-utils-kit';

const keyResponse = configApi.keyResponse;
const KEY_DATA = keyResponse.data;


module.exports = {
  fetchLogin(url, params, dataRely) {
    let {
      self, processor, route,
      storage, isLocalStoraged,
      email, password, _warning, } = dataRely;

    self.setState({ isWait: true, });

    timeoutPromise(1000, fetch(url, params))
      .then((res) => {
        if (res.status >= 200 && res.status < 300) {
          return res.json();
        } else {
          console.log(`[login] response code: ${res.status}`);
          self.setState({ isWait: false, });
          _warning();
        }
      })
      .then((resJson) => {
        let resData = resJson[KEY_DATA];

        let cache = {
          ...resData,
          password,
        };
        if (isLocalStoraged !== true) {
          processor(cache, storage);
        }
        global.g_user = cache;
        self.setState({ isWait: false, });

        // clean user info which already bind to self[this]
        self.email = self.password = null;
        self.isLocalStoraged = false;
        route();
      })
      .catch(error => console.error(error))
      .done();
  },

  saveLoginState: (cache, storage) => {
    storage.save({
      key: 'loginState',
      rawData: cache,
    });
  },

  openURL: (url, Linking) => {
    Linking.canOpenURL(url).then(supported => {
      if (!supported) {
        console.log(`can\'t handle url: ${url}`);
      } else {
        return Linking.openURL(url);
      }
    }).catch((err) => {
      console.log(`error occurred: ${err}`);
    })
  },
};

以上ES6 fetch会捕获下面的输出,我认为@Bergi是正确的,这是我的代码错误,而不是timeoutPromise错误。

2016-06-08 22:50:59.789 [info][tid:com.facebook.React.JavaScript] [login] response code: 400
2016-06-08 22:50:59.808 [error][tid:com.facebook.React.JavaScript] { [TypeError: undefined is not an object (evaluating 'KEY_DATA')]
  line: 103795,
  column: 29,
  sourceURL: 'http://172.26.129.189:8081/index.ios.bundle?platform=ios&dev=true' }
2016-06-08 22:50:59.810 [error][tid:com.facebook.React.JavaScript] One of the sources for assign has an enumerable key on the prototype chain. This is an edge case that we do not support. This error is a performance optimization and not spec compliant.
2016-06-08 22:50:59.810 [info][tid:com.facebook.React.JavaScript] 'Failed to print error: ', 'One of the sources for assign has an enumerable key on the prototype chain. This is an edge case that we do not support. This error is a performance optimization and not spec compliant.'

0 个答案:

没有答案