diff options
| author | Haishan <[email protected]> | 2019-04-19 00:16:01 +0800 |
|---|---|---|
| committer | Haishan <[email protected]> | 2019-04-19 00:17:06 +0800 |
| commit | e68f4ce9664f8164fd6aab284feb9ebed9f2ecdb (patch) | |
| tree | 3e94f49e44daebfb35089152b89cc2f02f3cfdcb /src/api | |
| parent | 54646e8fe650334aaccb5d0a0efeca21c203e54d (diff) | |
fix(streaming): split and join JSON string chunks correctly
for #13
Sometimes in Safari, in one "pump" you can get the content below(decoded
text string):
'{"up":0,"down":38589}\n{"up":0,"down":59928}'
and then JSON.parse will throw
Diffstat (limited to 'src/api')
| -rw-r--r-- | src/api/logs.js | 40 | ||||
| -rw-r--r-- | src/api/traffic.js | 29 |
2 files changed, 50 insertions, 19 deletions
diff --git a/src/api/logs.js b/src/api/logs.js index c8c3593..ed7e5af 100644 --- a/src/api/logs.js +++ b/src/api/logs.js @@ -1,6 +1,6 @@ import { getURLAndInit } from 'm/request-helper'; const endpoint = '/logs'; -const textDecoder = new TextDecoder('utf-8', { stream: true }); +const textDecoder = new TextDecoder('utf-8'); const getRandomStr = () => { return Math.floor((1 + Math.random()) * 0x10000).toString(16); @@ -8,8 +8,17 @@ const getRandomStr = () => { let even = false; let fetched = false; +let decoded = ''; + +function appendData(s, callback) { + let o; + try { + o = JSON.parse(s); + } catch (err) { + // eslint-disable-next-line no-console + console.log('JSON.parse error', JSON.parse(s)); + } -function appendData(o, callback) { const now = new Date(); const time = now.toLocaleString('zh-Hans'); // mutate input param in place intentionally @@ -21,21 +30,28 @@ function appendData(o, callback) { function pump(reader, appendLog) { return reader.read().then(({ done, value }) => { + const str = textDecoder.decode(value, { stream: !done }); + decoded += str; + + const splits = decoded.split('\n'); + + const lastSplit = splits[splits.length - 1]; + + for (let i = 0; i < splits.length - 1; i++) { + appendData(splits[i], appendLog); + } + if (done) { + appendData(lastSplit, appendLog); + decoded = ''; + // eslint-disable-next-line no-console console.log('GET /logs streaming done'); + fetched = false; return; + } else { + decoded = lastSplit; } - const t = textDecoder.decode(value); - const arrRawJSON = t.trim().split('\n'); - arrRawJSON.forEach(s => { - try { - appendData(JSON.parse(s), appendLog); - } catch (err) { - // eslint-disable-next-line no-console - console.log('JSON.parse error', JSON.parse(s)); - } - }); return pump(reader, appendLog); }); } diff --git a/src/api/traffic.js b/src/api/traffic.js index 68a7ff9..63252aa 100644 --- a/src/api/traffic.js +++ b/src/api/traffic.js @@ -1,6 +1,6 @@ import { getURLAndInit } from 'm/request-helper'; const endpoint = '/traffic'; -const textDecoder = new TextDecoder('utf-8', { stream: true }); +const textDecoder = new TextDecoder('utf-8'); const Size = 150; @@ -36,21 +36,36 @@ const traffic = { }; let fetched = false; +let decoded = ''; + +function parseAndAppend(x) { + traffic.appendData(JSON.parse(x)); +} function pump(reader) { return reader.read().then(({ done, value }) => { + const str = textDecoder.decode(value, { stream: !done }); + decoded += str; + + const splits = decoded.split('\n'); + + const lastSplit = splits[splits.length - 1]; + + for (let i = 0; i < splits.length - 1; i++) { + parseAndAppend(splits[i]); + } + if (done) { + parseAndAppend(lastSplit); + decoded = ''; + // eslint-disable-next-line no-console console.log('GET /traffic streaming done'); fetched = false; return; + } else { + decoded = lastSplit; } - const t = textDecoder.decode(value); - // console.log('response', t); - const o = JSON.parse(t); - - traffic.appendData(o); - return pump(reader); }); } |
