Calling all userscript developers: synchronous ajax (on the main thread) is bad, news at 11. We will soon trial blocking the use of jQuery’s async: false on the public beta and eventually live worlds. If you use this legacy feature, please rewrite your userscripts so all ajax calls are asynchronous.
Converting synchronous code
No ajax calls need to be synchronous. The easiest way to convert synchronous code to asynchronous code is to use ES2015’s promises and ES2017’s async functions, now supported by Chrome, Opera, Firefox 52, Safari 10.1 and soon Edge (currently insiders only). These two functions perform the same task:
var currentlyUpdatingLogs = false; async function updateLogs() { if (currentlyUpdatingLogs) throw "Don't read the logs twice at the same time!"; currentlyUpdatingLogs = true; var newLogs = []; for (var pageNum = 1; existUnreadLogs(newLogs); pageNum++) { Array.prototype.push.apply(newLogs, await getPageOfLogsAsync(pageNum)); } var logs = getSeenLogs(); Array.prototype.unshift.apply(logs, newLogs); storeSeenLogs(logs); currentlyUpdatingLogs = false; }
function updateLogs() { var newLogs = []; for (var pageNum = 1; existUnreadLogs(newLogs); pageNum++) { Array.prototype.push.apply(newLogs, getPageOfLogsSync(pageNum)); } var logs = getSeenLogs(); Array.prototype.unshift.apply(logs, newLogs); storeSeenLogs(logs); }
Can you spot the difference? Aside from a guard to avoid the function being called again mid-execution while idly waiting for a http request, there are only two:
- The function declaration has the keyword ‘async’ inserted before it.
- The call to get a page of logs has the keyword ‘await’ inserted before it.
There is generally very little refactoring required. You can see a demo of this function here. It’s also possible to emulate async functions by using generators, which are supported in more browsers. There is an example of this in the TW Best Friends userscript here.
Thanks in advance for doing your part to keep The West fast and responsive for our players 🙂