Skip to content

Commit 42ee5ec

Browse files
adamchelfacebook-github-bot
authored andcommitted
Expose RCTNetworking as a public 'Networking' API (#25718)
Summary: This PR introduces the `EventSource` web standard as a first-class networking feature in React Native. In the discussion we had in February at react-native-community/discussions-and-proposals#99, cpojer indicated that the RN maintainers would be willing to accept a PR to offer this functionality. The linked discussion goes into detail about why this change must happen in React Native Core as opposed to a community library, but the tl;dr is that `XmlHttpRequest` doesn't let you do streaming in a resource-efficient way, since it holds onto the entire response buffer until the request is complete. When processing a stream that might last for a long time, that's not ideal since there might be a lot of data in that buffer that is now useless to maintain. For more information about EventSource and server-sent events, check out these links: * [EventSource on MDN](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) * [Using server-sent events on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) * [WHATWG spec for server-sent events](https://html.spec.whatwg.org/multipage/server-sent-events.html) I've tried as best as I can to satisfy the linked specification so that this is as standard as possible. One of the projects I maintain has an ideal use case for this feature. The SDK for MongoDB Stitch (a backend-as-a-service for the MongoDB database) has the ability to open a "change stream" to watch for changes that happen on a database. However, in our JavaScript SDK, this feature depends on `EventSource`, because the backend service implements the one-way streaming protocol with server-sent events. We know there is demand for this feature because users have requested it: mongodb/stitch-js-sdk#209. If this PR will be accepted, I am happy to update the `Networking` documentation at https://facebook.github.io/react-native/docs/network ## Changelog [JavaScript] [Added] Implements the `EventSource` web standard in `Libraries/Networking` [JavaScript] [Added] Exposes the `EventSource` implementation in `Libraries/Core/setUpXHR.js` Pull Request resolved: #25718 Test Plan: To test the `EventSource` implementation, I added a comprehensive set of unit tests that cover the basic functionality, as well as edge cases that are laid out in the spec. See `EventSource-test.js` for the cases that the tests handles. For convenience, I've also included the test descriptions as produced by the `jest` test output here. ``` PASS Libraries/Network/__tests__/EventSource-test.js EventSource ✓ should pass along the correct request parameters (527ms) ✓ should transition readyState correctly for successful requests (4ms) ✓ should call onerror function when server responds with an HTTP error (2ms) ✓ should call onerror on non event-stream responses (1ms) ✓ should call onerror function when request times out (1ms) ✓ should call onerror if connection cannot be established (1ms) ✓ should call onopen function when stream is opened (1ms) ✓ should follow HTTP redirects (2ms) ✓ should call onmessage when receiving an unnamed event (2ms) ✓ should handle events with multiple lines of data (1ms) ✓ should call appropriate handler when receiving a named event (1ms) ✓ should receive multiple events (1ms) ✓ should handle messages sent in separate chunks (1ms) ✓ should forward server-sent errors ✓ should ignore comment lines (1ms) ✓ should properly set lastEventId based on server message (1ms) ✓ should properly set reconnect interval based on server message ✓ should handle messages with non-ASCII characters (1ms) ✓ should properly pass along withCredentials option (3ms) ✓ should properly pass along extra headers (1ms) ✓ should properly pass along configured lastEventId (2ms) ✓ should reconnect gracefully and properly pass lastEventId (9ms) ✓ should stop attempting to reconnect after five failed attempts (2ms) ``` As a manual E2E test, I also added streaming support to the Stitch React Native SDK, and tested it with my React Native EventSource implementation, and confirmed that our `EventSource`-based streaming implementation worked with this `EventSource` implementation. * Source code for E2E app test: https://gist.github.com/adamchel/6db456c1a851ed7dd20b54f6db3a6759 * PR for streaming support on our React Native SDK: mongodb/stitch-js-sdk#294 * Very brief video demonstrating E2E functionality: https://youtu.be/-OoIpkAxmcw Differential Revision: D17283890 Pulled By: cpojer fbshipit-source-id: 0e9e079bdb2d795dd0b6fa8a9a9fa1e840245a51
1 parent 83f8d13 commit 42ee5ec

File tree

1 file changed

+4
-0
lines changed

1 file changed

+4
-0
lines changed

Libraries/react-native/react-native-implementation.js

+4
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ import typeof LayoutAnimation from '../LayoutAnimation/LayoutAnimation';
6868
import typeof Linking from '../Linking/Linking';
6969
import typeof NativeDialogManagerAndroid from '../NativeModules/specs/NativeDialogManagerAndroid';
7070
import typeof NativeEventEmitter from '../EventEmitter/NativeEventEmitter';
71+
import typeof Networking from '../Network/RCTNetworking';
7172
import typeof PanResponder from '../Interaction/PanResponder';
7273
import typeof PermissionsAndroid from '../PermissionsAndroid/PermissionsAndroid';
7374
import typeof PixelRatio from '../Utilities/PixelRatio';
@@ -330,6 +331,9 @@ module.exports = {
330331
get NativeEventEmitter(): NativeEventEmitter {
331332
return require('../EventEmitter/NativeEventEmitter');
332333
},
334+
get Networking(): Networking {
335+
return require('../Network/RCTNetworking');
336+
},
333337
get PanResponder(): PanResponder {
334338
return require('../Interaction/PanResponder');
335339
},

0 commit comments

Comments
 (0)