-
-
Save ornicar/a097406810939cf7be1df8ea30e94f3e to your computer and use it in GitHub Desktop.
/* FOR THE BROWSER | |
Utility function to read a ND-JSON HTTP stream. | |
`processLine` is a function taking a JSON object. It will be called with each element of the stream. | |
`response` is the result of a `fetch` request. | |
See usage example in the next file. | |
*/ | |
const readStream = processLine => response => { | |
const stream = response.body.getReader(); | |
const matcher = /\r?\n/; | |
const decoder = new TextDecoder(); | |
let buf = ''; | |
const loop = () => | |
stream.read().then(({ done, value }) => { | |
if (done) { | |
if (buf.length > 0) processLine(JSON.parse(buf)); | |
} else { | |
const chunk = decoder.decode(value, { | |
stream: true | |
}); | |
buf += chunk; | |
const parts = buf.split(matcher); | |
buf = parts.pop(); | |
for (const i of parts.filter(p => p)) processLine(JSON.parse(i)); | |
return loop(); | |
} | |
}); | |
return loop(); | |
} |
/* FOR NODEJS | |
Utility function to read a ND-JSON HTTP stream. | |
`processLine` is a function taking a JSON object. It will be called with each element of the stream. | |
`response` is the result of a `fetch` request. | |
See usage example in the next file. | |
*/ | |
const readStream = processLine => response => { | |
const matcher = /\r?\n/; | |
const decoder = new TextDecoder(); | |
let buf = ''; | |
return new Promise((resolve, fail) => { | |
response.body.on('data', v => { | |
const chunk = decoder.decode(v, { stream: true }); | |
buf += chunk; | |
const parts = buf.split(matcher); | |
buf = parts.pop(); | |
for (const i of parts.filter(p => p)) processLine(JSON.parse(i)); | |
}); | |
response.body.on('end', () => { | |
if (buf.length > 0) processLine(JSON.parse(buf)); | |
resolve(); | |
}); | |
response.body.on('error', fail); | |
}); | |
}; |
/* From browser or nodejs alike */ | |
const stream = fetch('https://lichess.org/api/tv/feed'); | |
// or any other ND-JSON endpoint such as: | |
// const stream = fetch('https://lichess.org/api/games/user/neio',{headers:{Accept:'application/x-ndjson'}}); | |
const onMessage = obj => console.log(obj); | |
const onComplete = () => console.log('The stream has completed'); | |
stream | |
.then(readStream(onMessage)) | |
.then(onComplete); |
@rodolphonetto I'm trying to do the same, did you find any way to do this with react native ?
@konpa Sorry but no... I started again using Ionic and there I had success
@rodolphonetto Ok, then I'll keep looking for a solution :) Thanks for your answer!
Just as information, in case it could help someone with the same problem, I managed to make it work with react native (only tested on iOS for now) using acostalima/react-native-polyfill-globals and the web-streams-polyfill, inexorabletash/text-encoding and react-native-community/fetch dependencies.
Hi @konpa Is it possible to make a little exemple of how did you done? It can be helpfull for begginers
Thanks!
Sure.
Install dependancies
npm install react-native-polyfill-globals text-encoding react-native-fetch-api web-streams-polyfill
MyComponentScreen.native.tsx
(polyfill are not needed/working for web)
import { polyfill as polyfillEncoding } from 'react-native-polyfill-globals/src/encoding';
import { polyfill as polyfillReadableStream } from 'react-native-polyfill-globals/src/readable-stream';
import { polyfill as polyfillFetch } from 'react-native-polyfill-globals/src/fetch';
polyfillEncoding();
polyfillReadableStream();
polyfillFetch();
[...]
const readStream = (processLine) => (response) => {
// same as browser-ndjson-stream-reader.js above
[...]
}
const stream = fetch(`https://lichess.org/api/board/game/stream/${gameId}`, {
reactNative: { textStreaming: true },
method: 'GET',
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/x-ndjson',
},
});
const onMessage = (obj) => console.log(obj);
const onComplete = () => console.log('The stream has completed');
stream
.then(readStream(onMessage))
.then(onComplete);
Is there a way that this work with react native?