数据清除顺序错误。

huangapple go评论68阅读模式
英文:

Data is being cleared in the wrong order

问题

以下是您要翻译的内容:

"use strict";

// Set up some empty variables for the list of jobs (as HTML divs) are put in. This needs to be global for all the relevant functons to access.
let midCollectionData = "";
let senCollectionData = "";
let midApprovalData = "";
let senApprovalData = "";

// Same as above, but for the information at the bottom of the screen.
let infoArray = new Array;

// After the page is fully loaded, start all the functions.
$(document).ready(function() {
startApp();
});

// Start all the functions required to run the page.
function startApp() {
updateClock();
getData();
}

// The clock at the top right
function updateClock() {
var d = new Date(); // Get the date (from the system clock).
var s = ""; // Var to write a time into in a human readable format.
s += ((d.getHours() + 11) % 12 + 1) + ":"; // Get just the hours, add 11 and devide all that by 12. Take what is left over and add one. This converts 24hr time to 12hr time. Don't worry I did the math, it checks out.
s += (10 > d.getMinutes() ? "0" : "") + d.getMinutes(); // Get the minutes and make it always display a leading zero.
$("#clock").text(s); // Make the clock element display the time we just formatted.
$("#date").text(d.toDateString()); // Make the date element display the date we just formatted.
setTimeout(updateClock, 1000); // do it all again in 1000 milliseconds.
}

// Get the data from helpdesk using fetch()
function getData() {
fetch('/get-data') // Call the "get-data" function on the serverside python script
.then(response => response.json()) // Take the full response and store it in an object in a json structure
.then(data => populate(data))
.catch(error => console.error(error)); // Log any errors to the console
setTimeout(getData, 10000) // Do it all again in 10 seconds
}

// Get the approval status of each job as this information is not provided when getting info on all jobs.
async function getApproval(jobid) {
let response = await fetch(get-approval/${jobid});
let data = await response.json();
if (data.request.approval_status != null) {
return new Promise((resolve, reject) => {
resolve(data.request.approval_status.name);
})
}
else {
return new Promise((resolve, reject) => {
resolve("null");
})
}
}

// Populate the tables with the data from getData()
async function populate(data) {
await clearData();
await $.each(data.requests, async function(i, item) { // Loop through ONLY the requests items of the response data from the server
let approvalData;
await getApproval(item.id)
.then(function (result) {
approvalData = result;
});
makeItem(item.site.name, item.status.name, item.requester.name, item.id, approvalData); // Call makeItem() and pass the site, status, requester, and ID of the current item as arguments
});
await updateData(); // After the jobs are written (as html) to the variables, write them into the grid
}

function makeItem(campus, type, name, id, approval) { // Add the job's information to the correct list
let icon = "";
switch (approval) {
case "null":
icon = "";
break;
case "Approved":
icon = "done";
break;
case "Pending Approval":
icon = "schedule";
break;
case "Rejected":
icon = "close";
break;
}
// Check the site and status and then add to the data to that list as a div in html format
if (campus == "site1" && type == "Collection") {
midCollectionData += <div class='grid-item'>${name} (${id})</div>;
return;
}
if (campus == "site2" && type == "Collection") {
senCollectionData += <div class='grid-item'>${name} (${id}) ${icon}</div>;
return;
}
if (campus == "site1" && type == "Leadership") {
midApprovalData += <div class='grid-item'>${name} (${id})</div>;
return;
}
if (campus == "site2" && type == "Leadership") {
senApprovalData += <div class='grid-item'>${name} (${id}) ${icon}</div>;
return;
}
console.log(${name}, ${id}, ${campus}, ${type}, ${approval}, ${icon} slipped through the cracks); // Log any items to console that don't get sorted and display all infomation so we can investigate
return;
}

function clearData() { // Clear the data variables to stop double-ups of data
midCollectionData = "";
senCollectionData = "";
midApprovalData = "";
senApprovalData = "";
}

// Find the correct grid using the div's id and write the html data to it
function updateData() {
$("div.grid-item").remove(); // Clear the grids to stop double-ups of data
$("#Middle-Collection").html(midCollectionData);
$("#Senior-Collection").html(senCollectionData);
$("#Middle-Approval").html(midApprovalData);
$("#Senior-Approval").html(senApprovalData);
}

英文:

So this has got me stuck all day, I'm building out a simple noticeboard due to a infrastructure change and I won't be able to access a database directly. Fortunately the application (ManageEngine ServiceDesk) has an API that allows me to get the data I need. Unfortunately, I can't use Javascript to access the API because the just don't support it (I have tried) so I'm using python. The python side of this works fine, I am able to get all the data I need on that side.

The problem is I need to make several calls to the python side of things because the first call gets me the list of jobs according to my criteria, this works fine. Then I have to iterate over these jobs to make another call because I need to get approval status of each of the jobs. This also works fine, I console.log() the the info I need and it is displayed perfectly. If I don't clear the data fields (midCollectionData, etc) the site works fine but it keeps doubling up. So I need to clear them, but when I do the data either doesn't display at all or it doesn't display on the first run, but the second run works fine. Without requesting the approval data this all works fine (and is the current version being run) but we want to have an icon showing approval status and I believe that the issue is that I need to use async/await (otherwise the data is mixed up and isn't sorted correctly or the returned approval data is the promise and not the data, it has taken me a while since I'm not a professional).

Does anyone know what I need to do to make sure the data is cleared at the start of each run and that the data is written at the end of each run? Any help will be greatly appreciated. Also if you have any tips for improving code readability/efficiency that would be wonderful!

Thanks!

&quot;use strict&quot;;

// Set up some empty variables for the list of jobs (as HTML divs) are put in. This needs to be global for all the relevant functons to access.
let midCollectionData = &quot;&quot;;
let senCollectionData = &quot;&quot;;
let midApprovalData = &quot;&quot;;
let senApprovalData = &quot;&quot;;

// Same as above, but for the information at the bottom of the screen.
let infoArray = new Array;

// After the page is fully loaded, start all the functions.
$(document).ready(function() {
	startApp();
});

// Start all the functions required to run the page.
function startApp() {
	updateClock();
	getData();
}

// The clock at the top right
function updateClock() {
	var d = new Date(); // Get the date (from the system clock).
	var s = &quot;&quot;; // Var to write a time into in a human readable format.
	s += ((d.getHours() + 11) % 12 + 1) + &quot;:&quot;; // Get just the hours, add 11 and devide all that by 12. Take what is left over and add one. This converts 24hr time to 12hr time. Don&#39;t worry I did the math, it checks out.
	s += (10 &gt; d.getMinutes() ? &quot;0&quot; : &quot;&quot;) + d.getMinutes(); // Get the minutes and make it always display a leading zero.
	$(&quot;#clock&quot;).text(s); //bMake the clock element display the time we just formatted.
	$(&quot;#date&quot;).text(d.toDateString()); // Make the date element display the date we just formatted.
	setTimeout(updateClock, 1000); // do it all again in 1000 milliseconds.
}

// Get the data from helpdesk using fetch()
function getData() {
	fetch(&#39;/get-data&#39;) // Call the &quot;get-data&quot; function on the serverside python script
		.then(response =&gt; response.json()) // Take the full response and store it in an object in a json structure
		.then(data =&gt; populate(data))
		.catch(error =&gt; console.error(error)); // Log any errors to the console
	setTimeout(getData,10000) // Do it all again in 10 seconds
}

// Get the approval status of each job as this information is not provided when getting info on all jobs.
async function getApproval(jobid) {
	let response = await fetch(`get-approval/${jobid}`);
	let data = await response.json();
	if (data.request.approval_status != null) {
		return new Promise((resolve, reject) =&gt; {
			resolve(data.request.approval_status.name);
		})
	}
	else {
		return new Promise((resolve, reject) =&gt; {
			resolve(&quot;null&quot;);
		})
	}
}

// Populate the tables with the data from getData()
async function populate(data) {
	await clearData();
	await $.each(data.requests, async function(i, item) { // Loop through ONLY the requests items of the response data from the server
		let approvalData;
	    await getApproval(item.id)
			.then(function (result) {
				approvalData = result;
			});
		makeItem(item.site.name, item.status.name, item.requester.name, item.id, approvalData); // Call makeItem() and pass the site, status, requester, and ID of the current item as arguments
	});
	await updateData(); // After the jobs are written (as html) to the variables, write them into the grid
}

function makeItem(campus, type, name, id, approval) { // Add the job&#39;s information to the correct list
	let icon = &quot;&quot;;
	switch (approval) {
		case &quot;null&quot;:
			icon = &quot;&quot;;
			break;
		case &quot;Approved&quot;:
			icon = &quot;&lt;span class=&#39;material - symbols - outlined&#39;&gt;done&lt;/span&gt;&quot;;
			break;
		case &quot;Pending Approval&quot;:
			icon = &quot;&lt;span class=&#39;material - symbols - outlined&#39;&gt;schedule&lt;/span&gt;&quot;;
			break;
		case &quot;Rejected&quot;:
			icon = &quot;&lt;span class=&#39;material - symbols - outlined&#39;&gt;close&lt;/span&gt;&quot;;
			break;
	}
	// Check the site and status and then add to the data to that list as a div in html format
	if (campus == &quot;site1&quot; &amp;&amp; type == &quot;Collection&quot;) {
		midCollectionData += `&lt;div class=&#39;grid-item&#39;&gt;${name} (${id})&lt;/div&gt;`;
		return;
	}
	if (campus == &quot;site2&quot; &amp;&amp; type == &quot;Collection&quot;) {
		senCollectionData += `&lt;div class=&#39;grid-item&#39;&gt;${name} (${id}) ${icon}&lt;/div&gt;`;
		return;
	}
	if (campus == &quot;site1&quot; &amp;&amp; type == &quot;Leadership&quot;) {
		midApprovalData += `&lt;div class=&#39;grid-item&#39;&gt;${name} (${id})&lt;/div&gt;`;
		return;
	}
	if (campus == &quot;site2&quot; &amp;&amp; type == &quot;Leadership&quot;) {
		senApprovalData += `&lt;div class=&#39;grid-item&#39;&gt;${name} (${id}) ${icon}&lt;/div&gt;`;
		return;
	}
	console.log(`${name}, ${id}, ${campus}, ${type}, ${approval}, ${icon} slipped through the cracks`); // Log any items to console that don&#39;t get sorted and display all infomation so we can investigate
	return;
}

function clearData() { // Clear the data variables to stop double-ups of data
	midCollectionData = &quot;&quot;;
	senCollectionData = &quot;&quot;;
	midApprovalData = &quot;&quot;;
	senApprovalData = &quot;&quot;;
}

// Find the correct grid using the div&#39;s id and write the html data to it
function updateData() {
	$(&quot;div.grid-item&quot;).remove(); // Clear the grids to stop double-ups of data
	$(&quot;#Middle-Collection&quot;).html(midCollectionData);
	$(&quot;#Senior-Collection&quot;).html(senCollectionData);
	$(&quot;#Middle-Approval&quot;).html(midApprovalData);
	$(&quot;#Senior-Approval&quot;).html(senApprovalData);
}

I have tried moving the clearData() function around to diffrent places and making it an async (though I didn't expect this to actually work) but I can't find how to make it run in a certain order.

答案1

得分: 1

以下是翻译好的部分:

最有可能这个函数是罪魁祸首

async function populate(data) {
    await clearData();
    await $.each(data.requests, async function(i, item) { // 仅循环遍历响应数据中的请求项
        let approvalData;
        await getApproval(item.id)
            .then(function (result) {
                approvalData = result;
            });
        makeItem(item.site.name, item.status.name, item.requester.name, item.id, approvalData); // 调用makeItem()并传递当前项目的站点、状态、请求者和ID作为参数
    });
    await updateData(); // 在作业被写入变量(作为HTML)后,将它们写入网格
}

在处理异步函数时,最好避免使用'each'或'foreach'之类的函数,因为它们并不会按照你的期望执行。通常,你只需要使用for..of循环:

async function populate(data) {
  await clearData();

  for(const item of data.requests) {   
    const approvalData = await getApproval(item.id);
    makeItem(
      item.site.name,
      item.status.name,
      item.requester.name,
      item.id,
      approvalData
    );
  }

  await updateData();
}

我还强烈建议您不要使用makeItem来更新全局变量,并从updateData中获取它们。如果makeItem返回数据,updateData接收数据作为参数,事情会更明显和可预测。

最后,您在getApproval函数中做了一些奇怪的事情。尽量避免使用new Promise。可以这样重写它:

async function getApproval(jobid) {
    const response = await fetch(`get-approval/${jobid}`);
    const data = await response.json();
    if (data.request.approval_status !== null) {
       return data.request.approval_status.name;
    } else {
       return null;
    }
}

甚至更紧凑的写法:

async function getApproval(jobid) {
    const response = await fetch(`get-approval/${jobid}`);
    const data = await response.json();
    return data.request.approval_stats?.name ?? null;
}
英文:

Most likely this function is the culprit:

// Populate the tables with the data from getData()
async function populate(data) {
    await clearData();
    await $.each(data.requests, async function(i, item) { // Loop through ONLY the requests items of the response data from the server
        let approvalData;
        await getApproval(item.id)
            .then(function (result) {
                approvalData = result;
            });
        makeItem(item.site.name, item.status.name, item.requester.name, item.id, approvalData); // Call makeItem() and pass the site, status, requester, and ID of the current item as arguments
    });
    await updateData(); // After the jobs are written (as html) to the variables, write them into the grid
}

When working with async functions, it's best to avoid functions as 'each' or 'foreach' because they don't really do what you think.

Usually you just want for..of loops:

async function populate(data) {
  await clearData();

  for(const item of data.requests) {   
    const approvalData = await getApproval(item.id);
    makeItem(
      item.site.name,
      item.status.name,
      item.requester.name,
      item.id,
      approvalData
    );
  }

  await updateData();
}

I'd also really recommend you don't use makeItem to update a global variables and consume them from updateData. Things will work more obvious and predictable if makeItem returns data, and updateData receives data as an argument.

Lastly you're doing some strange stuff in the getApproval function. Avoid new Promise as much as you can. It can be rewritten this way:

async function getApproval(jobid) {
    const response = await fetch(`get-approval/${jobid}`);
    const data = await response.json();
    if (data.request.approval_status !== null) {
       return data.request.approval_status.name;
    } else {
       return null;
    }
}

Or even more compact

async function getApproval(jobid) {
    const response = await fetch(`get-approval/${jobid}`);
    const data = await response.json();
    return data.request.approval_stats?.name ?? null;
}

huangapple
  • 本文由 发表于 2023年4月4日 08:21:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/75924615.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定