Home > Software engineering >  How to execute Asynchronous Tasks Sequentially inside Synchronous Functions using React Native?
How to execute Asynchronous Tasks Sequentially inside Synchronous Functions using React Native?

Time:10-18

Problem:

I am trying to execute a series of functions in a specific order. These functions all have asynchronous tasks inside of them; however, these functions need to happen sequentially.

The below code needs to do the following:

  1. Delete current contents of Document Directory (this is because all files are persistent but I do NOT need them for permanent storage, only temporary)

  2. Copy current file assets from their locations to the Document Directory

  3. Zip up the folder of the Document Directory so I can store the zipped folder in AWS

Is it possible to ensure these functions wait for their asynchronous tasks to finish? (Some of these asynchronous tasks are run in a forEach loop -- this is not a single task within each function).

To take this a step further, can I execute the two (x2) copyFilesToDocumentDirectory() concurrently and still wait before executing zipDocumentDirectory()?

import React, { Component } from 'react';
import { zip } from 'react-native-zip-archive';
import RNFS from 'react-native-fs';

export default class AddMedia extends React.Component {
    
    state = { 
        photoAssets: [], 
        videoAssets: [], 
        videoThumbnails: [],
        thumbnailReady: false
    };

    zipDocumentDirectory() {
        var path = RNFS.DocumentDirectoryPath;
        console.log("Zipped");
        zip(path, path   "/urls.zip")
        .then((path) => {
            console.log("Zip complete");
        })
        .catch((err) => {
            console.log(err);
        });
    };

    deleteContentsOfDocumentDirectory() {
        var path = RNFS.DocumentDirectoryPath;
        var data = RNFS.readDir(path)
        .then((results) => {
            results.forEach(result => {
                /* I assume each item here is a FILE */
                RNFS.unlink(result.path)
                .then(() => {
                    console.log("File Deleted");
                })
                .catch((err) => {
                    console.log(err.message);
                });
            });
        });
    };

    copyFilesToDocumentDirectory(assets) {
        var path = RNFS.DocumentDirectoryPath;
        assets.forEach(asset => {
            RNFS.exists(asset.uri)
            .then((status) => {
                if(status) {
                    var newPath = path   "/"   asset.fileName;;
                    console.log("Copying from: ", asset.uri, " -- to: ", newPath);
                    RNFS.copyFile(asset.uri, newPath);
                };
            });
        });
    };
    
    storeToAWS() 
        this.deleteContentsOfDocumentDirectory();
        this.copyFilesToDocumentDirectory(this.state.photoAssets);
        this.copyFilesToDocumentDirectory(this.state.videoAssets);

        this.zipDocumentDirectory();
    
    };

    // ... Render code etc;
};

Efforts:

I wrote the above because that was the problem I am trying to solve. I thought this could be solved by Promises but I am relatively new to the idea of promises/async/await. I tried adding Promises to each method to wait for them to finish; however, the functions still ran synchronously and the asynchronous tasks ran after. The output is below the code showing the Zipped output inside zipDocumentDirectory() occurs BEFORE the asynchronous commands inside copyFilesToDocumentDirectory().

import React, { Component } from 'react';
import { zip } from 'react-native-zip-archive';
import RNFS from 'react-native-fs';

export default class AddMedia extends React.Component {
    
    state = { 
        photoAssets: [], 
        videoAssets: [], 
        videoThumbnails: [],
        thumbnailReady: false
    };

    zipDocumentDirectory() {
        var path = RNFS.DocumentDirectoryPath;
        console.log("Zipped");
        new Promise((resolve, reject) => {
            zip(path, path   "/urls.zip")
            .then((path) => {
                console.log("Zip complete");
                resolve();
            })
            .catch((err) => {
                console.log(err);
                reject();
            });
        });
    };

    deleteContentsOfDocumentDirectory() {
        var path = RNFS.DocumentDirectoryPath;
        new Promise((resolve, reject) => {
            var data = RNFS.readDir(path)
            .then((results) => {
                results.forEach(result => {
                    /* I assume each item here is a FILE */
                    RNFS.unlink(result.path)
                    .then(() => {
                        console.log("File Deleted");
                        resolve();
                    })
                    .catch((err) => {
                        console.log(err.message);
                        reject();
                    });
                });
            });
        });
    };

    copyFilesToDocumentDirectory(assets) {
        var path = RNFS.DocumentDirectoryPath;
        assets.forEach(asset => {
            new Promise((resolve, reject) => {
                RNFS.exists(asset.uri)
                .then((status) => {
                    if(status) {
                        var newPath = path   "/"   asset.fileName;;
                        console.log("Copying from: ", asset.uri, " -- to: ", newPath);
                        RNFS.copyFile(asset.uri, newPath);
                        resolve();
                    };
                });
            });
        });
    };
    
    storeToAWS = async () => {
        await this.deleteContentsOfDocumentDirectory();
        await this.copyFilesToDocumentDirectory(this.state.photoAssets);
        await this.copyFilesToDocumentDirectory(this.state.videoAssets);

        // 2. Zip temporary folder storage (with encryption)
        await this.zipDocumentDirectory();
OUTPUT:

 LOG  Zipped
 LOG  Copying from:  XYZ/FEB964FB-3ABB-4CF7-A3B0-1E90BD1932C4.jpg  -- to:  XYZ/FEB964FB-3ABB-4CF7-A3B0-1E90BD1932C4.jpg

CodePudding user response:

I added missing returns. I hope it will work now

import React, { Component } from 'react';
import { zip } from 'react-native-zip-archive';
import RNFS from 'react-native-fs';

export default class AddMedia extends React.Component {
    
    state = { 
        photoAssets: [], 
        videoAssets: [], 
        videoThumbnails: [],
        thumbnailReady: false
    };

    zipDocumentDirectory() {
        var path = RNFS.DocumentDirectoryPath;
        console.log("Zipped");
        return zip(path, path   "/urls.zip")
        .then((path) => {
            console.log("Zip complete");
        })
        .catch((err) => {
            console.log(err);
            reject();
        });
    };

    deleteContentsOfDocumentDirectory() {
        var path = RNFS.DocumentDirectoryPath;
        return RNFS.readDir(path)
        .then((results) => {
            return Promise.all(results.map(result => {
                return RNFS.unlink(result.path)
                .then(() => {
                    console.log("File Deleted");
                })
                .catch((err) => {
                     console.log(err.message);
                });
            }));
        });
    };

    copyFilesToDocumentDirectory(assets) {
        var path = RNFS.DocumentDirectoryPath;
        return Promise.all(assets.map(asset => {
            return RNFS.exists(asset.uri)
                .then((status) => {
                    if(status) {
                        var newPath = path   "/"   asset.fileName;;
                        return RNFS.copyFile(asset.uri, newPath);
                    };
                });
            });
        }));
    };
    
    storeToAWS = async () => {
        await this.deleteContentsOfDocumentDirectory();
        await this.copyFilesToDocumentDirectory(this.state.photoAssets);
        await this.copyFilesToDocumentDirectory(this.state.videoAssets);

        // 2. Zip temporary folder storage (with encryption)
        await this.zipDocumentDirectory();
    }
}
    ```
  • Related