three.js: Loaders - ObjectLoaders and other example loaders giving TypeError in react-native
[TypeError: undefined is not an object (evaluating ‘response.body.getReader’)]
Above error is produced when load function of any loader ( like GLTFLoader or ObjectLoader ) is called.
Platforms tested on:
Mobile - iPhone OS: iOS, MacOS Three.js version 0.135.0 expo-three version 6.0.1 expo-gl version 11.0.3 expo version 43.0.2 react version 17.0.1 react-native version 0.64.3
Sample Code:
const asset = Asset.fromModule(
require("./assets/v_knife_karam/v_knife_karam.gltf")
);
await asset.downloadAsync();
const loader = new GLTFLoader();
loader.load(
asset.uri,
(gltf) => {
// model = gltf.scene;
scene.add(gltf.scene);
},
(xhr) => {
console.log(`${(xhr.loaded / xhr.total) * 100}% loaded`);
},
(error) => {
console.error("An error happened", error);
}
);
Error : [TypeError: undefined is not an object (evaluating ‘response.body.getReader’)]
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 17 (10 by maintainers)
I think it’s more accurate to say that three.js made a change that exposed a bug in react-native / the polyfill. In terms of the benefits of the change the fetch implementation simplified the handling of data URIs in the FileLoader, is easier to follow, and personally I’d like to see Loaders take a set of fetch options in the future considering how much more ergonomic they are.
Have you created an issue for react-native, then? Again this is clearly a shortcoming of these other packages and limits the broader js ecosystems ability to leverage stable, modern APIs. Asking libraries to stall modernization to support workarounds for issues in other packages with no plan or effort to alleviate it is hard to support.
What I’m really asking for is for some effort to be made to fix the fetch polyfill and react native here instead of expecting three.js to revert because it’s the easy way out. I think instead this effort is best spent making a PR for github fetch to fix the
res.arrayBufferissue and informing or making a PR for react-native to improve the fetch behavior if that’s needed there too. Seeing what kind of progress can or can’t be made on either project I’d think would better inform decision made by three.js.And to be clear – like I’ve said before – this ultimately isn’t up to me but these are my opinions.
three.jsdoes not officially support node environments. As mentioned in the documentation (section Node.js), the engine is designed for the web and relies on Web APIs which are not necessarily supported in node.js.That said, we try make a node integration easier with PRs like #10732 or #14914 but only if the changes do not affect the code base too much.
In this particular case, the issue needs to be solved elsewhere like mentioned in https://github.com/mrdoob/three.js/issues/23015#issuecomment-994251807.
I feel what I’ve said is being twisted. I’m not advocating for alienating users… I’m advocating for this being fixed in the right location which I think is pretty clearly the polyfill or react-native. Can you help me understand why you’re so resistent to getting it fixed there? The React Native docs even recommend referencing the MDN docs on fetch for how to use it so it seems like a clear bug if
response.arrayBuffercan’t be used. Is there an issue in either project already to enable proper behavior in the future?If XMLHttpRequest support is going to be readded then I’d think we should just revert the FileLoader fetch change and not maintain two code paths.
I’m just suggesting that I don’t think it’s reasonable to expect three to hold on to such long outdated APIs because react native doesn’t support them but that’s just my opinion. If even basic fetch features such as
res.arrayBuffer()aren’t working I think the right place to fix this would be in react-native and/or the whatwg-fetch package. Ultimately the maintainers will have to weigh in, though.I don’t know exactly how react native works but as a workaround I’d expect you can override the global fetch polyfill with your own that implements whats needed in the mean time. Or you could override
THREE.FileLoader.prototype.loadwith an implementation from before r133.Which fetch polyfill is being used? At this point I’d submit an issue / fix to the polyfill library. In the Github polyfill, for example,
response.arrayBufferis only available ifBlobis supported by the environment which shouldn’t be necessary. Or I’d think you could provide a globalBlobpolyfill like this one I found so the fetch polyfill can leverage that implemenation.ReadableStreams are a lot newer but with the fetch API being stable for 6 years now I don’t think I support addressing this in three.js. I feel if libraries are going to enable running browser code in non browser contexts then they need to support long stable and commonly used browser features.
Like I mentioned in #22510 I’d think it should be possible to skip using the stream reader if it’s not supported in the environment. Something like this at the beginning of the initial
fetchcallback:It would be best if someone who’s familiar with the environments where it’s failing can make the PR and test to ensure the proposed solution works.