How to execute clipboard copy, window opening, event handler, and setInterval in synchronous fashion?












0















I am trying to do the following actions in order:
1. Create filename
2. Copy that filename to the clipboard
3. Open a window to a specific url
4. Click a specific div on the new window
5. Close the window
6. Now, I can print and simply paste the copied filename and finally print to pdf



I need these actions to happen one after the other. I need to run this logic inside of a loop (or at least execute it 200 times). So I need these steps to happen and THEN move to the next item in the html table that I am traversing.



let obj = {};

const copyToClipboard = (text) => {
const tempElem = document.createElement('input');
document.body.appendChild(tempElem);
tempElem.setAttribute('value', text);
tempElem.select();
document.execCommand("copy");
document.body.removeChild(tempElem);
};

const traverse = (i, inObj) => {
const number = document.getElementById('nid').rows[i].getElementsByTagName('td')[1].innerText;
const status = document.getElementById('nid').rows[i].getElementsByTagName('td')[4].innerText;
const file = `Item: ${name}`;

if(inObj[number] == "undefined" || inObj[poName] != status){
inObj[number] = status;
copyToClipboard(file);

let url = 'mysite.com/myroute';
let a = window.open(url);
a.focus();
let timer = setInterval(() => {
a.document.getElementsByClassName('anotherid')[1].click();
const i = a.document.getElementById('myframe');
i.contentWindow.focus();
i.contentWindow.print();
a.close();
clearInterval(timer);
console.log('Success!');
}, 1000);
} else{
console.log('Failure!');
}
};
for(let i = 0; i < tableSize; i++{
traverse(i, obj);
}


Some pieces of my code will execute before the others. For example, the windows will all open at once and then the remaining actions will take place. I need this code to execute completely inside of a loop before the next index iteration.










share|improve this question




















  • 2





    Wrap the async operations in Promises and chain them or use async/await with them.

    – Jared Smith
    Dec 29 '18 at 18:58











  • Everything in your question except setInterval() is synchronous because JavaScript runs synchronously. The callback from setInterval() will also run synchronously. It's just the timing function of the timer that will run asynchronously.

    – Scott Marcus
    Dec 29 '18 at 18:59











  • Where's your loop?

    – T.J. Crowder
    Dec 29 '18 at 19:08











  • Thanks everyone for the replies! I have added my loop and a revision.

    – God Complex
    Dec 29 '18 at 19:13
















0















I am trying to do the following actions in order:
1. Create filename
2. Copy that filename to the clipboard
3. Open a window to a specific url
4. Click a specific div on the new window
5. Close the window
6. Now, I can print and simply paste the copied filename and finally print to pdf



I need these actions to happen one after the other. I need to run this logic inside of a loop (or at least execute it 200 times). So I need these steps to happen and THEN move to the next item in the html table that I am traversing.



let obj = {};

const copyToClipboard = (text) => {
const tempElem = document.createElement('input');
document.body.appendChild(tempElem);
tempElem.setAttribute('value', text);
tempElem.select();
document.execCommand("copy");
document.body.removeChild(tempElem);
};

const traverse = (i, inObj) => {
const number = document.getElementById('nid').rows[i].getElementsByTagName('td')[1].innerText;
const status = document.getElementById('nid').rows[i].getElementsByTagName('td')[4].innerText;
const file = `Item: ${name}`;

if(inObj[number] == "undefined" || inObj[poName] != status){
inObj[number] = status;
copyToClipboard(file);

let url = 'mysite.com/myroute';
let a = window.open(url);
a.focus();
let timer = setInterval(() => {
a.document.getElementsByClassName('anotherid')[1].click();
const i = a.document.getElementById('myframe');
i.contentWindow.focus();
i.contentWindow.print();
a.close();
clearInterval(timer);
console.log('Success!');
}, 1000);
} else{
console.log('Failure!');
}
};
for(let i = 0; i < tableSize; i++{
traverse(i, obj);
}


Some pieces of my code will execute before the others. For example, the windows will all open at once and then the remaining actions will take place. I need this code to execute completely inside of a loop before the next index iteration.










share|improve this question




















  • 2





    Wrap the async operations in Promises and chain them or use async/await with them.

    – Jared Smith
    Dec 29 '18 at 18:58











  • Everything in your question except setInterval() is synchronous because JavaScript runs synchronously. The callback from setInterval() will also run synchronously. It's just the timing function of the timer that will run asynchronously.

    – Scott Marcus
    Dec 29 '18 at 18:59











  • Where's your loop?

    – T.J. Crowder
    Dec 29 '18 at 19:08











  • Thanks everyone for the replies! I have added my loop and a revision.

    – God Complex
    Dec 29 '18 at 19:13














0












0








0








I am trying to do the following actions in order:
1. Create filename
2. Copy that filename to the clipboard
3. Open a window to a specific url
4. Click a specific div on the new window
5. Close the window
6. Now, I can print and simply paste the copied filename and finally print to pdf



I need these actions to happen one after the other. I need to run this logic inside of a loop (or at least execute it 200 times). So I need these steps to happen and THEN move to the next item in the html table that I am traversing.



let obj = {};

const copyToClipboard = (text) => {
const tempElem = document.createElement('input');
document.body.appendChild(tempElem);
tempElem.setAttribute('value', text);
tempElem.select();
document.execCommand("copy");
document.body.removeChild(tempElem);
};

const traverse = (i, inObj) => {
const number = document.getElementById('nid').rows[i].getElementsByTagName('td')[1].innerText;
const status = document.getElementById('nid').rows[i].getElementsByTagName('td')[4].innerText;
const file = `Item: ${name}`;

if(inObj[number] == "undefined" || inObj[poName] != status){
inObj[number] = status;
copyToClipboard(file);

let url = 'mysite.com/myroute';
let a = window.open(url);
a.focus();
let timer = setInterval(() => {
a.document.getElementsByClassName('anotherid')[1].click();
const i = a.document.getElementById('myframe');
i.contentWindow.focus();
i.contentWindow.print();
a.close();
clearInterval(timer);
console.log('Success!');
}, 1000);
} else{
console.log('Failure!');
}
};
for(let i = 0; i < tableSize; i++{
traverse(i, obj);
}


Some pieces of my code will execute before the others. For example, the windows will all open at once and then the remaining actions will take place. I need this code to execute completely inside of a loop before the next index iteration.










share|improve this question
















I am trying to do the following actions in order:
1. Create filename
2. Copy that filename to the clipboard
3. Open a window to a specific url
4. Click a specific div on the new window
5. Close the window
6. Now, I can print and simply paste the copied filename and finally print to pdf



I need these actions to happen one after the other. I need to run this logic inside of a loop (or at least execute it 200 times). So I need these steps to happen and THEN move to the next item in the html table that I am traversing.



let obj = {};

const copyToClipboard = (text) => {
const tempElem = document.createElement('input');
document.body.appendChild(tempElem);
tempElem.setAttribute('value', text);
tempElem.select();
document.execCommand("copy");
document.body.removeChild(tempElem);
};

const traverse = (i, inObj) => {
const number = document.getElementById('nid').rows[i].getElementsByTagName('td')[1].innerText;
const status = document.getElementById('nid').rows[i].getElementsByTagName('td')[4].innerText;
const file = `Item: ${name}`;

if(inObj[number] == "undefined" || inObj[poName] != status){
inObj[number] = status;
copyToClipboard(file);

let url = 'mysite.com/myroute';
let a = window.open(url);
a.focus();
let timer = setInterval(() => {
a.document.getElementsByClassName('anotherid')[1].click();
const i = a.document.getElementById('myframe');
i.contentWindow.focus();
i.contentWindow.print();
a.close();
clearInterval(timer);
console.log('Success!');
}, 1000);
} else{
console.log('Failure!');
}
};
for(let i = 0; i < tableSize; i++{
traverse(i, obj);
}


Some pieces of my code will execute before the others. For example, the windows will all open at once and then the remaining actions will take place. I need this code to execute completely inside of a loop before the next index iteration.







javascript asynchronous dom promise async-await






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 29 '18 at 19:12







God Complex

















asked Dec 29 '18 at 18:56









God ComplexGod Complex

295




295








  • 2





    Wrap the async operations in Promises and chain them or use async/await with them.

    – Jared Smith
    Dec 29 '18 at 18:58











  • Everything in your question except setInterval() is synchronous because JavaScript runs synchronously. The callback from setInterval() will also run synchronously. It's just the timing function of the timer that will run asynchronously.

    – Scott Marcus
    Dec 29 '18 at 18:59











  • Where's your loop?

    – T.J. Crowder
    Dec 29 '18 at 19:08











  • Thanks everyone for the replies! I have added my loop and a revision.

    – God Complex
    Dec 29 '18 at 19:13














  • 2





    Wrap the async operations in Promises and chain them or use async/await with them.

    – Jared Smith
    Dec 29 '18 at 18:58











  • Everything in your question except setInterval() is synchronous because JavaScript runs synchronously. The callback from setInterval() will also run synchronously. It's just the timing function of the timer that will run asynchronously.

    – Scott Marcus
    Dec 29 '18 at 18:59











  • Where's your loop?

    – T.J. Crowder
    Dec 29 '18 at 19:08











  • Thanks everyone for the replies! I have added my loop and a revision.

    – God Complex
    Dec 29 '18 at 19:13








2




2





Wrap the async operations in Promises and chain them or use async/await with them.

– Jared Smith
Dec 29 '18 at 18:58





Wrap the async operations in Promises and chain them or use async/await with them.

– Jared Smith
Dec 29 '18 at 18:58













Everything in your question except setInterval() is synchronous because JavaScript runs synchronously. The callback from setInterval() will also run synchronously. It's just the timing function of the timer that will run asynchronously.

– Scott Marcus
Dec 29 '18 at 18:59





Everything in your question except setInterval() is synchronous because JavaScript runs synchronously. The callback from setInterval() will also run synchronously. It's just the timing function of the timer that will run asynchronously.

– Scott Marcus
Dec 29 '18 at 18:59













Where's your loop?

– T.J. Crowder
Dec 29 '18 at 19:08





Where's your loop?

– T.J. Crowder
Dec 29 '18 at 19:08













Thanks everyone for the replies! I have added my loop and a revision.

– God Complex
Dec 29 '18 at 19:13





Thanks everyone for the replies! I have added my loop and a revision.

– God Complex
Dec 29 '18 at 19:13












1 Answer
1






active

oldest

votes


















2














The only asynchronous thing I see in your code is traverse's completion. So simply define traverse to return a promise. Given the code in traverse, this is probably easiest if you do it explicitly:



const traverse = (i, inObj) => {
return new Promise((resolve, reject) => { // <===========================
const number = document.getElementById('nid').rows[i].getElementsByTagName('td')[1].innerText;
const status = document.getElementById('nid').rows[i].getElementsByTagName('td')[4].innerText;
const file = `Item: ${name}`;

if(inObj[number] == "undefined" || inObj[poName] != status){
inObj[number] = status;
copyToClipboard(file);

let url = 'mysite.com/myroute';
let a = window.open(url);
a.focus();
let timer = setInterval(() => {
a.document.getElementsByClassName('anotherid')[1].click();
const i = a.document.getElementById('myframe');
i.contentWindow.focus();
i.contentWindow.print();
a.close();
clearInterval(timer);
console.log('Success!');
resolve(); // <===========================
}, 1000);
// *** Probably want to do a timeout here in case the window never loads
} else{
console.log('Failure!');
reject(); // <===========================
}
});
};


Then:





  1. If you can use async syntax, write your loop using await on the promise returned by traverse. Example:



    // In an `async` function
    try {
    for (let i = 0; i < tableSize; ++i) {
    await traverse(i, obj);
    }
    // Done
    } catch (error) {
    // An error occurred
    }



  2. If not, chain your operations together by calling then on the promise returned by traverse:



    let promise = Promise.resolve();
    for (let i = 0; i < tableSize; ++i) {
    promise = promise.then(() => traverse(i, obj));
    }
    promise
    .then(() => {
    // Done
    })
    .catch(error => {
    // An error occurred
    };



Updating `tra






share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53972491%2fhow-to-execute-clipboard-copy-window-opening-event-handler-and-setinterval-in%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    The only asynchronous thing I see in your code is traverse's completion. So simply define traverse to return a promise. Given the code in traverse, this is probably easiest if you do it explicitly:



    const traverse = (i, inObj) => {
    return new Promise((resolve, reject) => { // <===========================
    const number = document.getElementById('nid').rows[i].getElementsByTagName('td')[1].innerText;
    const status = document.getElementById('nid').rows[i].getElementsByTagName('td')[4].innerText;
    const file = `Item: ${name}`;

    if(inObj[number] == "undefined" || inObj[poName] != status){
    inObj[number] = status;
    copyToClipboard(file);

    let url = 'mysite.com/myroute';
    let a = window.open(url);
    a.focus();
    let timer = setInterval(() => {
    a.document.getElementsByClassName('anotherid')[1].click();
    const i = a.document.getElementById('myframe');
    i.contentWindow.focus();
    i.contentWindow.print();
    a.close();
    clearInterval(timer);
    console.log('Success!');
    resolve(); // <===========================
    }, 1000);
    // *** Probably want to do a timeout here in case the window never loads
    } else{
    console.log('Failure!');
    reject(); // <===========================
    }
    });
    };


    Then:





    1. If you can use async syntax, write your loop using await on the promise returned by traverse. Example:



      // In an `async` function
      try {
      for (let i = 0; i < tableSize; ++i) {
      await traverse(i, obj);
      }
      // Done
      } catch (error) {
      // An error occurred
      }



    2. If not, chain your operations together by calling then on the promise returned by traverse:



      let promise = Promise.resolve();
      for (let i = 0; i < tableSize; ++i) {
      promise = promise.then(() => traverse(i, obj));
      }
      promise
      .then(() => {
      // Done
      })
      .catch(error => {
      // An error occurred
      };



    Updating `tra






    share|improve this answer






























      2














      The only asynchronous thing I see in your code is traverse's completion. So simply define traverse to return a promise. Given the code in traverse, this is probably easiest if you do it explicitly:



      const traverse = (i, inObj) => {
      return new Promise((resolve, reject) => { // <===========================
      const number = document.getElementById('nid').rows[i].getElementsByTagName('td')[1].innerText;
      const status = document.getElementById('nid').rows[i].getElementsByTagName('td')[4].innerText;
      const file = `Item: ${name}`;

      if(inObj[number] == "undefined" || inObj[poName] != status){
      inObj[number] = status;
      copyToClipboard(file);

      let url = 'mysite.com/myroute';
      let a = window.open(url);
      a.focus();
      let timer = setInterval(() => {
      a.document.getElementsByClassName('anotherid')[1].click();
      const i = a.document.getElementById('myframe');
      i.contentWindow.focus();
      i.contentWindow.print();
      a.close();
      clearInterval(timer);
      console.log('Success!');
      resolve(); // <===========================
      }, 1000);
      // *** Probably want to do a timeout here in case the window never loads
      } else{
      console.log('Failure!');
      reject(); // <===========================
      }
      });
      };


      Then:





      1. If you can use async syntax, write your loop using await on the promise returned by traverse. Example:



        // In an `async` function
        try {
        for (let i = 0; i < tableSize; ++i) {
        await traverse(i, obj);
        }
        // Done
        } catch (error) {
        // An error occurred
        }



      2. If not, chain your operations together by calling then on the promise returned by traverse:



        let promise = Promise.resolve();
        for (let i = 0; i < tableSize; ++i) {
        promise = promise.then(() => traverse(i, obj));
        }
        promise
        .then(() => {
        // Done
        })
        .catch(error => {
        // An error occurred
        };



      Updating `tra






      share|improve this answer




























        2












        2








        2







        The only asynchronous thing I see in your code is traverse's completion. So simply define traverse to return a promise. Given the code in traverse, this is probably easiest if you do it explicitly:



        const traverse = (i, inObj) => {
        return new Promise((resolve, reject) => { // <===========================
        const number = document.getElementById('nid').rows[i].getElementsByTagName('td')[1].innerText;
        const status = document.getElementById('nid').rows[i].getElementsByTagName('td')[4].innerText;
        const file = `Item: ${name}`;

        if(inObj[number] == "undefined" || inObj[poName] != status){
        inObj[number] = status;
        copyToClipboard(file);

        let url = 'mysite.com/myroute';
        let a = window.open(url);
        a.focus();
        let timer = setInterval(() => {
        a.document.getElementsByClassName('anotherid')[1].click();
        const i = a.document.getElementById('myframe');
        i.contentWindow.focus();
        i.contentWindow.print();
        a.close();
        clearInterval(timer);
        console.log('Success!');
        resolve(); // <===========================
        }, 1000);
        // *** Probably want to do a timeout here in case the window never loads
        } else{
        console.log('Failure!');
        reject(); // <===========================
        }
        });
        };


        Then:





        1. If you can use async syntax, write your loop using await on the promise returned by traverse. Example:



          // In an `async` function
          try {
          for (let i = 0; i < tableSize; ++i) {
          await traverse(i, obj);
          }
          // Done
          } catch (error) {
          // An error occurred
          }



        2. If not, chain your operations together by calling then on the promise returned by traverse:



          let promise = Promise.resolve();
          for (let i = 0; i < tableSize; ++i) {
          promise = promise.then(() => traverse(i, obj));
          }
          promise
          .then(() => {
          // Done
          })
          .catch(error => {
          // An error occurred
          };



        Updating `tra






        share|improve this answer















        The only asynchronous thing I see in your code is traverse's completion. So simply define traverse to return a promise. Given the code in traverse, this is probably easiest if you do it explicitly:



        const traverse = (i, inObj) => {
        return new Promise((resolve, reject) => { // <===========================
        const number = document.getElementById('nid').rows[i].getElementsByTagName('td')[1].innerText;
        const status = document.getElementById('nid').rows[i].getElementsByTagName('td')[4].innerText;
        const file = `Item: ${name}`;

        if(inObj[number] == "undefined" || inObj[poName] != status){
        inObj[number] = status;
        copyToClipboard(file);

        let url = 'mysite.com/myroute';
        let a = window.open(url);
        a.focus();
        let timer = setInterval(() => {
        a.document.getElementsByClassName('anotherid')[1].click();
        const i = a.document.getElementById('myframe');
        i.contentWindow.focus();
        i.contentWindow.print();
        a.close();
        clearInterval(timer);
        console.log('Success!');
        resolve(); // <===========================
        }, 1000);
        // *** Probably want to do a timeout here in case the window never loads
        } else{
        console.log('Failure!');
        reject(); // <===========================
        }
        });
        };


        Then:





        1. If you can use async syntax, write your loop using await on the promise returned by traverse. Example:



          // In an `async` function
          try {
          for (let i = 0; i < tableSize; ++i) {
          await traverse(i, obj);
          }
          // Done
          } catch (error) {
          // An error occurred
          }



        2. If not, chain your operations together by calling then on the promise returned by traverse:



          let promise = Promise.resolve();
          for (let i = 0; i < tableSize; ++i) {
          promise = promise.then(() => traverse(i, obj));
          }
          promise
          .then(() => {
          // Done
          })
          .catch(error => {
          // An error occurred
          };



        Updating `tra







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Dec 29 '18 at 19:18

























        answered Dec 29 '18 at 19:13









        T.J. CrowderT.J. Crowder

        682k12112091306




        682k12112091306






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53972491%2fhow-to-execute-clipboard-copy-window-opening-event-handler-and-setinterval-in%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Monofisismo

            Angular Downloading a file using contenturl with Basic Authentication

            Olmecas