Page 1 of 1

Loop through array!

Posted: Sat Feb 27, 2021 1:01 am
by MY001
I am little bit confused how Switch scripting works. I read in a post that the when the job arrives to a scripting step, the sendToSingle function does not execute until script is fully done. What I am trying to achieve is that I have jobs in form of xml and within the xml theres a metadata contain a list of urls and I want to loop through those links and send each of them as a job and attach privatedata for alter call to be downloaded.

The issue I am encountering is that is that when I loop through array with "For" method, it always returns the last element of the array and it send the jobs to next outgoing flow with the last element of the array in all jobs

Let's for example say I have an array of ["Url1", "Url2","Url3"] , Switch sends 3 jobs and all of them carry privatedata of "Url3" while I want 3 jobs and each of them have a privatedata if url1 for 1st, url2 for 2nd and url3 for 3rd.

I tried different ways by adding index to the loop so the index will increase with every loop but I still get same result .

Below is one of the codes that that I tried
async function jobArrived(s,flowElement,job){

let links= await parseXPathAsString("file","/JSON/array/urls",job);
let cleanURLs= links.match(/\bhttps?:\/\/\S+/gi);


for(let i = 0; cleanURLs.length > i; i++) {
if (cleanURLs.indexOf('dropbox') != -1){
cleanURLs = cleanURLs.replace('dl=0', 'dl=1');

}

await job.setPrivateData("Link",cleanURLs);

await job.sendToSingle(job.get());
}
}


Any idea how to achieve looping through the Urls in the array and send amount of job based on how many urls exists in the array and each job MUST carry one url out of the array and have it as privatedata?

Thank you

Re: Loop through array!

Posted: Sat Feb 27, 2021 11:47 am
by borisCM
Hi,

i have not tested it but i think like this it should work:

inside the loop you will need to make child jobs Job.createChild(path: string): Promise<Job>
and than also in the loop you will need to set the private data for each child jobs Job.setPrivateData(tag: string, value: string): Promise<void>
also in the loop you will need to send the new created child jobs to the output with Job.sendToSingle(newName?: string): Promise<void>

after the loop you will need to send the original job to null, because you don't need it anymore.

hope this helps

kind regards

Re: Loop through array!

Posted: Sat Feb 27, 2021 12:05 pm
by borisCM
this a simple working example

Code: Select all

async function jobArrived(s: Switch, flowElement: FlowElement, job: Job) {

    let numberOfJobs:number = 5
    let jobPath:string = await job.get(AccessLevel.ReadOnly);

    for (let jobs:number = 1; jobs <= numberOfJobs; jobs++){
        let childJob:Job = await job.createChild(jobPath);
        await childJob.setPrivateData("number",jobs.toString())
        await childJob.sendToSingle(jobs + ".xml");
    }
await job.sendToNull
}

Re: Loop through array!

Posted: Fri Apr 09, 2021 11:47 pm
by stargazerllc
Using the array functions instead of for each might be a better solution. The most common are .map(), .forEach() and .reduce()

Reference https://developer.mozilla.org/en-US/doc ... ects/Array

Code: Select all

 const myArr = [val1, val2, val3]
 
 const functionThatProcessesEachValueIndividually = (value)=>{
 // do something to the individual value of the array that is passed into this function.

 }

// performs actions on each element of array
myArr.forEach(functionThatProcessesEachValueIndividually)
 
 // performs actions and puts the return values in the place of the element. 
const newValues = myArr.map(functionThatProcessesEachValueIndividually)

// this would replace your for loop
const replacerFunction = (url) => url.replace('dl=0', 'dl=1')
const replacedUrls = cleanURLs.map(replacerFunction)
// which can also be written as 
const replacedUrls = cleanURLs.map((url) => url.replace('dl=0', 'dl=1'))