While it is generally a good idea to avoid pulling data from the server to make response times faster, sometimes you run into a requirement where ajax is necessary. Today, most of CRM's callbacks require synchronous results. A good example is the pre search callback on lookup controls. If you want to apply a filter based on an AJAX call, you either run an ajax call in the on load and disable the control until the ajax call completes or do synchronous ajax in the presearch event. Running the ajax in the on load isn't a good solution because you may be running an unnecessary query whose results may never even be used because the user just opened the form to view it or might change fields that the ajax call was dependent on before they get to the control you're filtering meaning you have to reissue another request and disable the control until you get a result. The other option of synchronous ajax is also very bad because it will freeze the browser UI and you can't show a spinner or anything while it is running.
It would be great if CRM allowed passing a promise back from all or most callbacks to indicate that the callback is doing asynchronous processing. CRM would indicate to the user that the operation is being processed with a spinner or whatever UI is appropriate for the given callback. Once the promise resolves, operation would continue.
It would be great if most or all callbacks allowed async processing especially callbacks like on save and pre search.
(On save, you can sometimes work around by preventing the save then calling Xrm.Page.data.entity.save() once your asynchronous call is complete but that won't work with special save types like deactivate, saving activities as completed, or qualifying a lead.)