recursively call a JS function that uses promises

2019-07-10 00:24发布

问题:

I am trying to write a function that recursively calls itself to write a blob to disk in chunks. While the recursion works and the chunks progress, I'm messing up on how to handle the return promises as the function instantiates its own promise and needs to return when the write is complete. writeFile2 is first called from the invoking function with isAppend=false.

function writeFile2( path, file, blob, isAppend)
    {
        var csize = 4 * 1024 * 1024; // 4MB
        var d = $q.defer();
        console.log ("Inside write file 2 with blob size="+blob.size);

        // nothing more to write, so all good?
        if (!blob.size)
        {
            // comes here at the end, but since d is instantiated on each
            // call, I guess the promise chain messes up and the invoking
            // function never gets to .then
            console.log ("writefile2 all done");
            d.resolve(true);
            return d.promise; 
        }
        // first time, create file, second time onwards call append

        if (!isAppend)
        {
            $cordovaFile.writeFile(path, file, blob.slice(0,csize), true)
            .then (function (succ) {
                    return writeFile2(path,file,blob.slice(csize),true);
            },
            function (err) {
                d.reject(err);
                return d.promise;

            });
        }
        else
        {
         $cordovaFile.writeExistingFile(path, file, blob.slice(0,csize))
         .then (function (succ) {
                 return writeFile2(path,file,blob.slice(csize),true);
         },
         function (err) {
             d.reject(err);
             return d.promise;

         });   
        }

        return d.promise;
    }

回答1:

When you invoke another method, return the promise that is returned instead of your own. When there's no work to do, return your own promise.

function writeFile2( path, file, blob, isAppend) {
    var csize = 4 * 1024 * 1024; // 4MB
    console.log ("Inside write file 2 with blob size="+blob.size);

    // nothing more to write, so all good?
    if (!blob.size)
    {
        // nothing to do, just resolve to true
        console.log ("writefile2 all done");
        return $q.resolve(true); 
    }
    // first time, create file, second time onwards call append

    if (!isAppend)
    {
        // return the delegated promise, even if it fails
        return $cordovaFile.writeFile(path, file, blob.slice(0,csize), true)
            .then (function (succ) {
                return writeFile2(path,file,blob.slice(csize),true);
            });
    }
    else
    {
        // return the delegated promise, even if it fails
        return $cordovaFile.writeExistingFile(path, file, blob.slice(0,csize))
            .then (function (succ) {
                return writeFile2(path,file,blob.slice(csize),true);
            });   
    }
}