Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation #46

Closed
DonikaV opened this issue Jun 23, 2017 · 5 comments · Fixed by #47
Closed

TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation #46

DonikaV opened this issue Jun 23, 2017 · 5 comments · Fixed by #47

Comments

@DonikaV
Copy link

DonikaV commented Jun 23, 2017

export const sendSuggestion = ((data: any): Promise<any> => {
  console.log(JSON.stringify(data));
const apiUrl = `/api/suggest/`;
return fetch(apiUrl, {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify(data)
}).then(checkStatus)
    .then(r => r.json())
    .then(data => {
        console.log(data);
    });
});

const checkStatus = ((response: any) => {
  if (response.ok) {
    return response;
  } else {
    var error = new Error(response.statusText);
    console.log(error);
  //return Promise.reject(error);
  }
})

The script crashed with error
TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
After webkack it is looks:


exports.sendSuggestion = function (data) {
    var apiUrl = "/api/suggest/";
    return unfetch_1.default(apiUrl, {             //Code crashed here
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
    }).then(checkStatus).then(function (r) {
        return r.json();
    }).then(function (data) {
        console.log(data);
    });
};
var checkStatus = function checkStatus(response) {
    if (response.ok) {
        return response;
    } else {
        var error = new Error(response.statusText);
        console.log(error);
    }
};
@developit
Copy link
Owner

Ah interesting, the .default is causing the context to switch to fetch instead of window. That's actually a incorrect behavior from Webpack / Babel though, are you able to post any details about your setup?

@DonikaV
Copy link
Author

DonikaV commented Jun 24, 2017

You mean webpack setup?

jhnns added a commit to jhnns/unfetch that referenced this issue Jun 26, 2017
@QuentinRoy
Copy link

QuentinRoy commented Jun 27, 2017

I have the same issue using Webpack 3 and Babel (babel-preset-env).

Original code:

import fetch from 'unfetch';
const test = fetch('http://localhost:8080');

Compiled code:

/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_unfetch__ = __webpack_require__(420);


const test = __WEBPACK_IMPORTED_MODULE_2_unfetch__["a" /* default */]('http://localhost:8080');

Note how unfetch is called with __WEBPACK_IMPORTED_MODULE_2_unfetch__ as context. I am not sure it is compliant with the ES module standard.

Fails on Chrome with

Uncaught (in promise) TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation

and on Firefox with

Function.prototype.bind called on incompatible target

Interestingly, Safari doesn't care.

The following workaround works well.

import unfetch from 'unfetch';

// Fix a bug making unfetch not being properly bound with webpack.
const fetch = unfetch;

const test = fetch('http://localhost:8080');

A simple fix for unfetch could be to replace

export default typeof fetch=='function' ? fetch : function(url, options) {
  // [...]
}

with something like

export default typeof fetch=='function' ? fetch.bind() : function(url, options) {
  // [...]
}

If it is of any use, here is my webpack config.

const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

const resolve = relPath => path.resolve(__dirname, relPath);

module.exports = {
  entry: {
    experiment: ['babel-polyfill', './experiment'],
    'results-viewer': ['babel-polyfill', './results-viewer']
  },
  output: {
    path: resolve('build'),
    publicPath: '/',
    filename: './[name].js'
  },
  context: resolve('src'),
  resolve: {
    extensions: ['.js', '.json', '.jsx', '.css'],
    alias: {
      'state-machine': 'javascript-state-machine'
    }
  },
  module: {
    rules: [{
      test: /\.pug/,
      include: resolve('src'),
      use: 'pug-loader'
    }, {
      test: /\.s?css$/,
      include: resolve('src'),
      use: ExtractTextPlugin.extract({
        use: [{
          loader: 'css-loader',
          options: { sourceMap: true }
        }, {
          loader: 'postcss-loader',
          options: { sourceMap: true }
        }, {
          loader: 'sass-loader',
          options: { sourceMap: true }
        }]
      })
    }, {
      test: /\.css$/,
      exclude: resolve('src'),
      use: ExtractTextPlugin.extract({
        use: [{
          loader: 'css-loader',
          options: { sourceMap: true }
        }]
      })
    }, {
      test: /\.m?js$/,
      include: resolve('src'),
      use: 'babel-loader'
    }]
  },
  plugins: [
    new ExtractTextPlugin({ filename: '[name].css', disable: false, allChunks: true }),
  ]
};

and my .babelrc

{
  "presets": [["env", {
    "targets": { "browsers": "last 1 chrome version, last 1 safari version, last 1 firefox version" },
    "modules": false,
    "loose": true
  }]],
  "plugins": ["transform-runtime"]
}

@LasaleFamine
Copy link

Seems like this is still a thing. I'm using:

  • isomorphic-unfetch 3.0.0
  • next 9.1.3
  • react 16.11.0

On server side it's working as expected, but when I try something like making a call inside a simple useEffect I get the error. The workaround of using const fetch = unfetch.bind() worked for me as well.

@jbaiter
Copy link

jbaiter commented Jun 22, 2021

Running into the same issue with Parcel v2.0beta.3 :-/

jtbandes added a commit to foxglove/just-fetch that referenced this issue Jul 8, 2021
Fetch doesn't work in browsers when it's not bound to the window — for example, `fetch.call({}, "...")` raises `TypeError: Can only call Window.fetch on instances of Window` in Safari and `TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation` in Chrome.

Webpack currently generates something that looks like:
```ts
const just_fetch_1 = tslib_1.__importDefault(require("@foxglove/just-fetch"));
...
await just_fetch_1.default(...)
```
And this means the fetch function executes with `this` being just_fetch_1 rather than window.

I'm not sure how Webpack normally handles issues like this (see also developit/unfetch#46) but we can work around it with an explicit bind.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants