Search code examples
react-nativecamera-roll

CameraRoll.saveToCameraRoll "Write Busy" error when saving multiple images


I have a "save all" function in my React Native (for iOS) photo app that grabs the array of images and passes them to the CameraRoll.saveToCameraRoll function.

This is my function to save them:

saveAllToCameraRoll = () => {
    for (let image of this.state.downloadList) {   
        CameraRoll.saveToCameraRoll(image.uri); 
    }
};

downloadList is an array of Firebase objects referencing images stored on Firebase storage:

[
    -uid1234 : {
        uri: "https://firebasestorage.googleapis.com/....",
        uploadUser: {
            ....
        }
    },
    ....
]

This all seems to work, and works fine for single/few images, but if downloadList gets too large (seemingly 11 images) it starts throwing a warning and some images wont get saved. The warning is:

Possible Unhandled Promise Rejection Error: Write Busy

and also:

Error saving cropped image: Error Domain=ALAssetsLibraryErrorDomainCode=-3301 "Write Busy"

It seems simple, that you can't save so many so quickly or it freezes up, but I can find no documentation on how to wait for it to finish one to start the next.


Solution

  • CameraRoll.saveToCameraRoll returns a Promise, so you can wait for it to finish with:

    saveAllToCameraRoll = async () => {
        for (let image of this.state.downloadList) {   
            await CameraRoll.saveToCameraRoll(image.uri); 
        }
    };
    

    Or with Airbnb's recommended way:

    this.state.downloadList.reduce((prev, { uri }) =>
      prev.then(() => CameraRoll.saveToCameraRoll(uri), Promise.resolve()));
    

    If you still want to execute a few of the operations in parallel, you can iterate with a step and wrap the operations in each iteration with Promise.all.