I am writing a server call to populate a map. I cant seem to get the code correct as to where it will wait until the Server Call is finished before moving on. I wrote the below function DoIt that calls someTimeConsumingthing that calls the server and populates the map. It will do the Server Call in SomeTimeConsumingThing however it will then Jump out of the function and go to the next code block.
export function onBeforePriceRules(quote, lineModels, conn) {
var varQuoteHostid;
if (lineModels.length) {
var varProdIds = [];
//Might want to do a function here.
lineModels.forEach(function (line) {
varQuoteHostid = quote.record["Host__c"];
var varProdId = line.record["SBQQ__Product__c"];
if (varProdId) {
varProdIds.push(varProdId);
}
});
}
const UniqueProdList = [...new Set(varProdIds)];
var ProdIdList = "('" + UniqueProdList.join("', '") + "')";
let myMap;
var ProductMap = new Map();
//Call DoIt
doit(conn, ProdIdList, ProductMap).then(function () {
console.log("Now finally done!");
debugger;
});
var NewVarable = "NewThing";
console.log("NewVarable" + NewVarable);
debugger;
return Promise.resolve();
}
function someTimeConsumingThing(conn, ProdIdList, ProductMap) {
console.log("someTimeConsumingThing");
debugger;
conn
.query("SELECT Id, Model__c FROM Product2 WHERE ID IN" + ProdIdList)
.then(async function (returnedRecords) {
if (returnedRecords.totalSize) {
returnedRecords.records.forEach(function (record) {
ProductMap.set(record.Id, record);
console.log("ProductMap" + ProductMap);
debugger;
});
}
});
return ProductMap;
}
async function doit(conn, ProdIdList, ProductMap) {
console.log("Calling someTimeConsumingThing");
debugger;
await someTimeConsumingThing(conn, ProdIdList, ProductMap);
console.log("Ready with someTimeConsumingThing");
debugger;
}
You are creating a promise when you use
conn
.query("SELECT Id, Model__c FROM Product2 WHERE ID IN" + ProdIdList)
and you extend that promise by calling then which literally means do some thing after the promise has resolved. The problem is that you are not waiting for that promise anywhere, but instead you create a new one right after that, which you return and await in doit function.
return new Promise(function (resolve, reject) {
setTimeout(resolve, 2000);
});
What you want is to wait for the actual query promise, so edit your someTimeConsumingThing to return query promise, like so
function someTimeConsumingThing(conn, ProdIdList, ProductMap) {
console.log("someTimeConsumingThing");
debugger;
// Imagine this as a block, that executes some time somewhere.
// Everything outside of it gets executed when you call this function
return conn
.query("SELECT Id, Model__c FROM Product2 WHERE ID IN" + ProdIdList)
.then(async function (returnedRecords) {
if (returnedRecords.totalSize) {
returnedRecords.records.forEach(function (record) {
ProductMap.set(record.Id, record);
console.log("ProductMap" + ProductMap);
debugger;
});
}
});
}
Same with async/await syntax
async function someTimeConsumingThing(conn, ProdIdList, ProductMap) {
console.log("someTimeConsumingThing");
debugger;
// Await for the query results
const returnedRecords = await conn
.query("SELECT Id, Model__c FROM Product2 WHERE ID IN" + ProdIdList)
if (returnedRecords.totalSize) {
returnedRecords.records.forEach(function (record) {
ProductMap.set(record.Id, record);
console.log("ProductMap" + ProductMap);
debugger;
});
}
return whateveryouwant
}
Read more about promises here and dont be afraid to google how they work and/or explanation for them!