Warning: The magic method SFML_Singleton::__wakeup() must have public visibility in /home/public/wp-content/plugins/sf-move-login/inc/classes/class-sfml-singleton.php on line 72

Warning: Cannot modify header information - headers already sent by (output started at /home/public/wp-content/plugins/sf-move-login/inc/classes/class-sfml-singleton.php:72) in /home/public/wp-includes/rest-api/class-wp-rest-server.php on line 1642

Warning: Cannot modify header information - headers already sent by (output started at /home/public/wp-content/plugins/sf-move-login/inc/classes/class-sfml-singleton.php:72) in /home/public/wp-includes/rest-api/class-wp-rest-server.php on line 1642

Warning: Cannot modify header information - headers already sent by (output started at /home/public/wp-content/plugins/sf-move-login/inc/classes/class-sfml-singleton.php:72) in /home/public/wp-includes/rest-api/class-wp-rest-server.php on line 1642

Warning: Cannot modify header information - headers already sent by (output started at /home/public/wp-content/plugins/sf-move-login/inc/classes/class-sfml-singleton.php:72) in /home/public/wp-includes/rest-api/class-wp-rest-server.php on line 1642

Warning: Cannot modify header information - headers already sent by (output started at /home/public/wp-content/plugins/sf-move-login/inc/classes/class-sfml-singleton.php:72) in /home/public/wp-includes/rest-api/class-wp-rest-server.php on line 1642

Warning: Cannot modify header information - headers already sent by (output started at /home/public/wp-content/plugins/sf-move-login/inc/classes/class-sfml-singleton.php:72) in /home/public/wp-includes/rest-api/class-wp-rest-server.php on line 1642

Warning: Cannot modify header information - headers already sent by (output started at /home/public/wp-content/plugins/sf-move-login/inc/classes/class-sfml-singleton.php:72) in /home/public/wp-includes/rest-api/class-wp-rest-server.php on line 1642

Warning: Cannot modify header information - headers already sent by (output started at /home/public/wp-content/plugins/sf-move-login/inc/classes/class-sfml-singleton.php:72) in /home/public/wp-includes/rest-api/class-wp-rest-server.php on line 1642
{"id":264,"date":"2018-06-15T07:45:30","date_gmt":"2018-06-15T13:45:30","guid":{"rendered":"http:\/\/www.munderwood.ca\/?p=264"},"modified":"2018-06-15T07:45:59","modified_gmt":"2018-06-15T13:45:59","slug":"side-effects-of-js-data-http-and-async-operations","status":"publish","type":"post","link":"https:\/\/www.munderwood.ca\/index.php\/2018\/06\/15\/side-effects-of-js-data-http-and-async-operations\/","title":{"rendered":"Side effects of js-data-http and async operations"},"content":{"rendered":"

Recently I encountered a rather strange scenario, wherein I created two different\u00a0findAll<\/span>\u00a0operations using the js-data-http<\/a> adapter for a js-data<\/a> query, only to see two identical network requests emitted. The root of the problem turned out to be that I was creating a single object to hold the query options and reusing it across requests, in combination with the fact that js-data-http mutates its parameters in place during asynchronous operation.<\/p>\n

\/\/ This will find posts from user 4 twice!\r\nconst opts = { force: true };\r\nstore.findAll('post', { userId: 2 }, opts);\r\nstore.findAll('post', { userId: 4 }, opts);<\/pre>\n

Here is a brief demonstration of the behaviour<\/a>. In the fiddle two requests are made to the JSONPlaceholder test API<\/a>, for posts from different users. When the responses are received, they both contain the posts for the user specified in the second query.<\/p>\n

The simple solution is to not use the same object for multiple requests.<\/p>\n

\/\/ This works as expected.\r\nstore.findAll('post', { userId: 2 }, { force: true });\r\nstore.findAll('post', { userId: 4 }, { force: true });<\/pre>\n

Why does this work?<\/h2>\n

Or more interestingly, why doesn’t<\/em> the first method work?<\/p>\n

Part of the process js-data-http uses is to move the query object passed as the second argument to\u00a0findAll<\/span>\u00a0into a new property of the third argument,\u00a0options.params<\/span>. This is because the function that actually makes the network request expects any query parameters to be specified in\u00a0options.params<\/span>, at least in part because the query parameter format used in GET requests is not the same as the JSON-formatted query syntax<\/a> used by js-data. So some<\/em> amount of transformation is required between what we pass in to js-data and what it sends to the server.<\/p>\n

However, because the transformation is done in place, js-data mutates the object that is passed into it. The chain of events goes roughly as follows, due to the asynchronous promise-based nature of the findAll<\/span>\u00a0 operation.<\/p>\n