简体   繁体   中英

Javascript : wait for for loop to finish before executing next loop

I have a scenario where I have to delete attachments first and then upload new attachments. Here is my code:

        var programs = this.UploadModel.getProperty("/programs/items"); 

        //Delete files first
        for(var i=0; i<filesToDelete.length; i++){
            oThis._callAttachmentWS("DELETE", proj, filesToDelete[i]);
        }

        //Then save new files   
        for(var i=0; i<programs.length; i++){
            oThis._callAttachmentWS("SAVE", proj, programs[i]);
        }

How do I make the second for loop wait for the first loop to finish?

Since the OP within the comments states...

"... it calls a web service and the return is true or false"

"... the function is coming from another controller. It can be changed. Since it's an ajax call, then callback back is most likely supported"

... and looking at how...

oThis._callAttachmentWS("DELETE", proj, filesToDelete[i]);

... respectively...

oThis._callAttachmentWS("SAVE", proj, programs[i]);

... are being used, one could assume the _callAttachmentWS method returns a Promise .

Promise.all and Promise.allSettled are two methods each operating upon the states of a list of promises and returning a promise itself.

The next provided example code utilizes the latter method. The implementation also mocks the behavior of an asynchronous (promise returning) _callAttachmentWS method. There are promise returning helper functions for the also mocked file save/delete tasks. The main task, called handleFileDeleteAndFileSave , shows a possible solution of how one could handle the promise chain(s)...

 function callAttachmentWS(action, project, fileName) { return new Promise( (resolve, reject) => { setTimeout(() => { // file deletion completed. resolve({ action, fileName }); }, 3000); } ); } // var programs = this.UploadModel.getProperty("/programs/items"); // //Delete files first // for(var i=0; i<filesToDelete.length; i++){ // oThis._callAttachmentWS("DELETE", proj, filesToDelete[i]); // } // // //Then save new files // for(var i=0; i<programs.length; i++){ // oThis._callAttachmentWS("SAVE", proj, programs[i]); // } function triggerFileActions(action, fileList) { console.log(`+++ trigger ${ action.toLowerCase() } files +++`); // returns an array of promises. return fileList.map(fileName => /*oThis._*/callAttachmentWS(action, 'my-project-name', fileName) ) } function deleteFiles(fileList) { // returns a promise. return Promise.allSettled(triggerFileActions('DELETE', fileList)); } function saveFiles(fileList) { // returns a promise. return Promise.allSettled(triggerFileActions('SAVE', fileList)); } function handleFileDeleteAndFileSave(deleteList, saveList) { // returns a promise. return deleteFiles( deleteList ).then(deleteResultList => { deleteResultList.forEach(result => console.log(result)); console.log('... delete files finished...'); }).then(() => { // returns a promise. return saveFiles( saveList ).then(saveResultList => { saveResultList.forEach(result => console.log(result)); console.log('... save files finished...'); }).then(() => '+++ handleFileDeleteAndFileSave is settled +++'); }); } const filesToDelete = ['foo', 'bar', 'baz']; const programs = ['bizz', 'buzz']; handleFileDeleteAndFileSave( filesToDelete, programs, ).then(status => console.log(status));
 .as-console-wrapper { min-height: 100%;important: top; 0; }

As the above code shows, the properly timed handling of file delete/save is based on nested promise chains. In order to free the programmers' minds from writing and maintaining such structures the async... await syntax was introduced.

The next code example repeats the above code block, just in a more imperative programming style...

 async function callAttachmentWS(action, project, fileName) { return new Promise( (resolve, reject) => { setTimeout(() => { // file deletion completed. resolve({ action, fileName }); }, 3000); } ); } function triggerFileActions(action, fileList) { console.log(`+++ trigger ${ action.toLowerCase() } files +++`); // returns an array of promises. return fileList.map(fileName => callAttachmentWS(action, 'my-project-name', fileName) ) } async function deleteFiles(fileList) { // returns a promise. return Promise.allSettled(triggerFileActions('DELETE', fileList)); } async function saveFiles(fileList) { // returns a promise. return Promise.allSettled(triggerFileActions('SAVE', fileList)); } async function handleFileDeleteAndFileSave(deleteList, saveList) { // handles promises (async functions) via `await` syntax, // thus it makes it an async function too // which (implicitly) returns a promise. const deleteResultList = await deleteFiles(deleteList); deleteResultList.forEach(result => console.log(result)); console.log('... delete files finished...'); const saveResultList = await saveFiles(saveList); saveResultList.forEach(result => console.log(result)); console.log('... save files finished...'); return '+++ handleFileDeleteAndFileSave is settled +++'; } const filesToDelete = ['foo', 'bar', 'baz']; const programs = ['bizz', 'buzz']; (async function () { const status = await handleFileDeleteAndFileSave(filesToDelete, programs); console.log(status); }());
 .as-console-wrapper { min-height: 100%;important: top; 0; }

You can use async/await. Here is more about them

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM