سؤال

I use HTML5's filesystem feature in my project. And try to write text append to a file continuously by using for-loop. But actually it just effect one write which is the last write, even though I got 5 "Write completed."(That should means it success writing 5 times). Here is my code:

window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
var fs;

function initFS() {
    console.log("init filesystem")
    window.requestFileSystem(window.TEMPORARY, 1024 * 1024, function (filesystem) {
        fs = filesystem;
        console.log(fs);
    }, errorHandler);
}

function errorHandler(e) {
    var msg = '';
    switch (e.code) {
        ...
    };
    console.log('Error: ' + msg);
}

function receiveFile(cont) {
    fs.root.getFile('log.txt', {
        create: true
    }, function (fileEntry) {
        // Create a FileWriter object for our FileEntry (log.txt).
        fileEntry.createWriter(function (fileWriter) {
            fileWriter.seek(fileWriter.length);
            fileWriter.onwriteend = function (e) {
                console.log('Write completed.');
            };
            fileWriter.onerror = function (e) {
                console.log('Write failed: ' + e.toString());
            };
            // Create a new Blob and write it to log.txt.
            var bb = new Blob([cont]);
            fileWriter.write(bb);
        }, errorHandler);
    }, errorHandler);
}

function foo() {
    for (i = 0; i < 5; i++) {
        setTimeout(function () { // // it works, BTW: Why it didn't write the num in ascending order as expected
            (function (x) {
                receiveFile(x);
            })(i)
        }, i * 1000);
        //receiveFile(i); // didn't work, just write once
    }
}

window.addEventListener("load", initFS, false);

You can try it on jsfiddle and get result from this link: filesystem:http://fiddle.jshell.net:0/temporary/

I am thinking about whether if it write so fast that can not be save in time. So I try 'setTimeout' on it and it works and write completely.

Anyone know why?. How I can implement what I want? Appreciate first if you can help me.

هل كانت مفيدة؟

المحلول

fileWriter.write() is an asynchronous operation. You basically created a race here. What happens without the timeouts (or even with the timeouts if the writes are slow):

  • receiveFile(0)
  • fileWriter.seek(fileWriter.length /* == 0 */)
  • queue write(0)
  • receiveFile(1)
  • fileWriter.seek(fileWriter.length /* == 0 */) - Yeah, still 0 as there was no actual write performed yet.
  • queue write(1)
  • ...
  • actual async write(0)
  • actual async write(1)
  • ...

The rest of what happens is down the implementation details and bugs. So in conclusion: Always wait for write operations to finish before doing another write.

The current spec draft actually disallows calling seek/write when readyState === WRITING, and states that readyState should be set to WRITING as soon as the write function gets called. Chrome does not implement this version of the spec yet, or is still buggy, or else if would have caught your race and thrown InvalidStateError on the second call to .seek() (timeout-less version).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top