This blog goes down as a request from my blog readers. And also a question from my clients whenever I take up an upgrade project and convert the existing XmlHttpRequest sync requests to Xrm.WebApi.
Before I proceed further, let me clear the air of confusion to begin with. There is no facility in dynamics WebApi to execute this as synchronous and rightfully so. After all the synchronous XmlHttp calls have already been deprecated in the browsers and soon they will cease to work.
But wait, if you have come this far you won’t be disappointed. I this blog I am going to explain on how you can execute Xrm.WebApi calls to execute in sync with few simple changes in the way you invoke them. You will be amazed to see how this simple trick can actually make the steps execute synchronous even with calls of Xrm.WebApi. So let’s start our journey now.
Below is a sample scenario. In the below code, “executeOnLoad” function is fired when the function registered on formload event of the record. Here the requirement is retrieveOperation1 should complete first, then statement 2 shall be execute and then finally the retrieveOperation2 should be complete. Once retrieveOperation2 is completed successfully the formLoad function shall complete. The console should log the statements in this order.
- operation1 completed successfully
- printing statement 2
- operation2 completed successfully.
// form onload method.
function executeOnLoad() {
// executeOnLoad is the function called on form onload.
// statement 1
retrieveOperation1();
// statement 2 - this should execute after statement 1 is completed.
console.log("printing statement 2");
// statement 3
retrieveOperation2();
}
function retrieveOperation1() {
Xrm.WebApi.retrieveMultipleRecords("account", "?$select=name")
.then(function (results) {
console.log("operation1 completed successfully.");
}, function (error) {
});
}
function retrieveOperation2() {
Xrm.WebApi.retrieveMultipleRecords("account", "?$select=name")
.then(function (results) {
console.log("operation2 completed successfully.");
}, function (error) {
});
}
And below is the output in the console.
Quite obvious isn’t it? Xrm.WebApi functions are promise functions. The code will not wait for the retrieveMultipleRecords operation to complete. It is asynchronous. So statement 2 got printed and after that operation1 and operation2. The output sometimes differ. If operation1 takes more time, then it is even possible that Operation2 statement is printed and then Operation1.
Obviously it is not working as per our expectations. So what can we do about it? Well we have the wonderful async and await feature in Javascript. I wrote a blog on this sometime back but not specifically on Xrm.WebApi.
Below is the modified code to achieve our requirement.
// form onload method.
async function executeOnLoad() {
// statement 1
await retrieveOperation1();
// statement 2 - this should execute after statement 1 is completed.
console.log("printing statement 2");
// statement 3
await retrieveOperation2();
// statement 4
console.log("onload event successfully completed.");
}
async function retrieveOperation1() {
var results = await Xrm.WebApi.retrieveMultipleRecords("account", "?$select=name");
for (var e = 0; e < results.entities.length; e++) {
// perform your operations here.
}
console.log("retrieve1 operation completed successfully.");
}
async function retrieveOperation2() {
var results = await Xrm.WebApi.retrieveMultipleRecords("account", "?$select=name");
for (var e = 0; e < results.entities.length; e++) {
// perform your operations here.
}
console.log("retrieve2 operation completed successfully.");
}
Below are the changes I made
- Modified the function called on form onload – executeOnLoad to async method.
- Changed the functions retrieveOperation1 and retrieveOperation2 to async methods.
- Used the keyword “await” on Xrm.WebApi methods. await can be used with Promise based functions which Xrm.WebApi functions are. Hence the await keyword before them just works fine for us.
- Just to make things complicated, I have introduced an additional console.log statement post retrieveOperation2 completion.
And now when I run this, I see all the operations executed in order. Wonderful isn’t it.
Observe that the final console.log statement executed post Operation2 completion only. The onload event completion didn’t happen until all the previous steps were completed.
Got quite a few requests to upload a working video. Here is the same.
Tested this if Edge/ Edge chromium/ FireFox/ Chrome and it just worked fine. Word of caution here – this won’t work in IE 11
Where you should execute sync and where not – “depends on your requirement”. But this little know tactic certainly is an additional tool in repertoire to implement whenever required.
Hope this helped!
You may also like these posts
Debajit Dutta
(Business Solutions MVP)
Discover more from Debajit's Power Apps & Dynamics 365 Blog
Subscribe to get the latest posts sent to your email.