【问题标题】:TypeError: Failed to execute 'fetch' on 'Window': Invalid valueTypeError:无法在“窗口”上执行“获取”:无效值
【发布时间】:2018-08-13 01:46:26
【问题描述】:

我尝试使用 fetch 从后端调用 react,没有库(例如 Axios)。所以我创建了这个函数:

export function api(url, method, body, isHeaderContentType,isRequestHeaderAuthentication,header, succesHandler, errorHandler) {
const prefix = 'link';
console.log("url:",prefix+url);
const contentType = isHeaderContentType ? {
    'Content-Type': 'application/json',
} : {};
const auth = isRequestHeaderAuthentication
    ? {
        Authorization: `Bearer ${AuthUtils.getTokenUser}`,
    }
    : {};
fetch(prefix + url, {
    method,
    headers: {
        ...contentType,
        ...auth,
        ...header,

    },
    protocol:'http:',
    body,
})
    .then(response => {
        response.json().then(json => {
            if (response.ok) {
                console.log("method", json);
                if (succesHandler) {
                    succesHandler(json)
                }
            } else {
                return Promise.reject(json)
            }
        })
    })
    .catch(err => {
        console.log("error",`${url}  ${err}`);
        if (errorHandler) {
            errorHandler(err);
        }
    })

} 并这样称呼它

api(
            `link`,
            "GET",
            null,
            true,
            true,
            null,
            response => {
                this.setState({profile:response.data})
            },
            err => {
                console.log('error', err);
            }
        );

我在这个函数中调用了我的 api():

getProfileUser = () =>{
    if (!isUserAuthenticated()){
        history.push('/signin')
    }else {
        api(
            `link`,
            "GET",
            null,
            true,
            true,
            null,
            response => {
                this.setState({profile:response.data})
            },
            err => {
                console.log('error', err);
            }
        );
    }
};

这是我的完整组件:

export default class Profile extends Component {
constructor(props) {
    super(props);
    this.state = {
        profile:[]
    }

}
getProfileUser = () =>{
    if (!isUserAuthenticated()){
        someCode
    }else {
        api(
            `link`,
            "GET",
            null,
            true,
            true,
            null,
            response => {
                this.setState({profile:response.data})
            },
            err => {
                console.log('error', err);
            }
        );
    }
};

componentDidMount() {
    this.getProfileUser();
}

render(){
    return(
        <div>
            hello 
        </div>
    )
}

}

但是当我尝试运行它时,我收到了这样的错误

TypeError: 无法在 'Window' 上执行 'fetch': 无效值

有人知道我的代码有什么问题吗?该功能在我使用“POST”方法时有效,但在我使用“GET”方法时无效

【问题讨论】:

  • 你什么时候打电话给api()?您是在组件生命周期方法中调用它吗?如果有,是哪一个?
  • @Stretch0 是的,我试图在 componentwillmount 上调用它
  • 如果你尝试在componentDidMount()中调用它是否有效?
  • @Stretch0 不,我仍然遇到同样的错误
  • 这是一个奇怪的问题,但你可以尝试添加这个吗? const fetch = window.fetch.bind(window);

标签: javascript reactjs fetch


【解决方案1】:

当我尝试在我的 fetch 调用中添加 Authorization 标头时,这也发生在我身上。在我的情况下,它是由标题字符串中的换行符引起的,即Bearer:\nsomelong-token。将新行更改为空格即可解决问题。

【讨论】:

  • 发生在我身上,因为我有另一个角色(你不能轻易看到的那个)。很好的提示。
  • 我对客户端中的所有标头使用 encodeURI,在节点中使用 decodeURI。解决问题。
【解决方案2】:

对我来说,我在标题对象的 key 中有一个无效字符。我不小心包含了“:”,这会引发所描述的错误。在 chrome 控制台中很难直观地看到。希望它可以帮助某人。

{ 'Authorization:':'Bearer etc...' }

【讨论】:

  • 这很难找到。感谢分享,具体什么时候出现这个不明显!
  • @tresf 知道这对我造成的痛苦 - 我很高兴我可以减轻别人的痛苦!
  • 谢谢,我遇到了同样的错误。如果没有这个,我永远不会在我的 js 中找到。
【解决方案3】:

我在将带有换行符的字符串传递到标题对象时遇到了这个问题,例如:

const myString = 'this is a string \nand this is a new line';
headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${token}`,
    'subscriptionId': myString
}

【讨论】:

  • 这似乎有效。当任何参数中存在不允许的字符时,可能会遇到此类问题。在将字符串作为参数传递给任何函数之前,请确保对字符串使用 trim()。尤其是 REST 服务
【解决方案4】:

嘿,我在尝试使用 react 中的 fetch 方法加载数据时遇到了同样的问题。

const response = await fetch('/graphql', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    query
  })
});

我在 Content-Type 中有一个额外的空间导致错误,所以请查找相同的空间。

【讨论】:

    【解决方案5】:

    我遇到了同样的问题,但是在使用 Angular 7 时,我使用的是这样的拦截器服务:

    // headerservice.ts
    public intercept() {
        const token = Cookies.get('token');
        this.Language = Cookies.get('language');
        this.headers = new HttpHeaders(
          {
            Authorization: 'JWT ' + token,
            'Accept-Language': this.Language
          }
        );
        return this.headers;
      }
    
      //other file 
       this.headers = this.headersService.intercept();
    

    但它不适用于我正在执行提取的其他文件,因此我删除了服务并将标题直接放在函数中并且它可以工作! 像这样:

    const token = Cookies.get('token');
    const language = Cookies.get('language');
    const headers = { 
     Authorization: 'JWT ' + token,
    'Accept-Language': language
    }
    const fetchParams = { method: 'GET',
               headers: (headers) };
    fetch(url, fetchParams)
    

    【讨论】:

      【解决方案6】:

      对我来说,发生错误是因为我在调用 fetch() 时在 GET 请求中包含了“正文”。排除 GET 请求的主体解决了问题(例如,如果您正在编写处理不同 HTTP 请求类型的通用函数或框架)。这是一个简单的代码摘录来说明解决方案(显然,此代码在现实世界中需要扩展,但它说明了这一点):

      // Earlier code that specifies the HTTP method
      let method = 'GET';
      
      // Create fetch() init object
      let fetchInit = {};
      if (method !== 'GET') {
        fetchInit.body = yourRequestBody;
      }
      
      // Start network request
      fetch(url, fetchInit).then...
      

      【讨论】:

        【解决方案7】:

        这个错误也发生在我身上,但是在不同的情况下。我想分享它以防其他人遇到此问题。

        所以当我尝试在不使用 FormData 的情况下使用 HTTP POST 上传文件时,出现错误“TypeError: Failed to execute 'fetch' on 'Window': Invalid value”。为了解决这个问题,我使用了 FormData 对象并附加了属性和文件本身:

        let formData = new FormData();
        formData.append('name', fileName);
        formData.append('data', file);
        

        然后我使用 fetch 通过 POST 方法发送文件。这是伪代码:

        const options = {method: 'POST', formData};
        fetch('http://www.someURL.com/upload', options);
        

        【讨论】:

          【解决方案8】:

          我已经解决了这个问题,将我的前端 url 添加到我的后端代码的白名单中

          【讨论】:

            【解决方案9】:

            就我而言,这是因为我写的是“Content Type”而不是“Content-Type”

            【讨论】:

              【解决方案10】:

              当我像这样对标头进行字符串化时出现此错误:

              fetch(http://example.com,
              {
                  credentials: "include",
                  headers: JSON.stringify({
                      foo: localStorage.getItem("foo"),
                  }),
              })
              

              我通过删除 JSON.stringify 来修复它:

              fetch(http://example.com,
              {
                  credentials: "include",
                  headers: {
                      foo: localStorage.getItem("foo"),
                  },
              })
              

              【讨论】:

                【解决方案11】:

                我遇到过类似的问题- “无证 类型错误:无法在“窗口”上执行“获取”:值不是有效的字节字符串。”

                在使用 Swagger 进行测试时。在我检查了介于两者之间的令牌后,它得到了解决。请务必从 Web 浏览器复制令牌,如果字符串很长,他们往往会使用省略号(...)。

                【讨论】:

                • 另一个原因可能是您没有复制整个令牌..彻底检查令牌值以确定原因.. 通常在 SSOToken 下显示的 chrome 浏览器令牌{ tkn 在 sub tkn 正确后是短的一个及以下
                【解决方案12】:

                对我来说,解决方案是不在 GET 方法上发送正文。

                async request(url, method, data) {
                    const options = {
                        headers: {
                            "Content-Type": "application/json",
                            "Accept": "application/json"
                        },
                        method: method,
                        credentials: "include"
                    };
                
                    if (['POST', 'PUT', 'DELETE'].includes(method)) {
                        options.body = JSON.stringify(data);
                    }
                
                    return await fetch(url, options);
                }
                

                【讨论】:

                • 能否提供您使用的代码示例以供其他人参考?
                猜你喜欢
                • 1970-01-01
                • 2021-04-26
                • 2019-10-13
                • 1970-01-01
                • 1970-01-01
                • 2015-07-07
                • 2014-04-29
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多