javascript-如何确定已读取所有文件并解决承诺

以下代码负责读取文件.我的要求是如何查找是否已读取所有文件,以便可以从父函数(readmultifiles)返回或解决承诺.

        $.when(readmultifiles(files))
               .then(function(){//all files uploaded}))

Above code initiates the file read. What can be done so that upon reading of all files
callback is done or a return can be made.

        function readmultifiles(files) {               
            // Read first file
            setup_reader(files, 0);
        }


        function setup_reader(files, i) {
            var file = files[i];
            var name = file.name;
            var reader = new FileReader();
            reader.onload = function(e) {
                readerLoaded(e, files, i, name);
            };
            reader.readAsBinaryString(file);
            // After reading, read the next file.
        }

        function readerLoaded(e, files, i, name) {
            // get file content  
            var bin = e.target.result;
            // do sth with text


            // If there's a file left to load
            if (i < files.length - 1) {
                // Load the next file
                setup_reader(files, i + 1);
            }
        }

解决方法:

在一个好的设计中,应考虑到您的实现可以从中学习的一些事项:

>从最低级别的异步操作中创建承诺(称为“承诺”).然后,您可以使用promise功能来控制逻辑流并传播错误,并且可以用promise一致地实现您的代码.在这种情况下,这意味着您应该保证readFile()正确.它还使readFile()在您的项目中或将来的项目中的其他地方更加有用.
>确保您始终正确地传播错误.在不使用promise的情况下使用异步代码,很难正确地将错误返回给原始调用者,尤其是如果异步逻辑最终变得复杂(使用嵌套或序列操作)时.
>请仔细考虑您的异步操作是否必须是序列或它们是否可以并行运行.如果一个操作不依赖于另一个操作,并且您不太可能因多个请求而使某些服务过载,那么并行运行事物通常会更快地获得结果.
>通过异步函数返回承诺,以便调用者可以知道何时完成操作并可以访问异步结果.
>不要不必要地围绕现有的承诺创建另一个承诺(被视为承诺反模式之一).
>如果使用jQuery Promise,请尝试坚持与Promise标准兼容的jQuery功能,以免将来遇到互操作性问题,也不会使将来的代码读者更可能知道标准Promise如何工作.

有了所有这些,这里有五种方法来实现您的代码-使用标准的Promise,使用jQuery Promise和您的操作序列或并行运行以及使用Bluebird Promise.在所有情况下,最后都将获得一系列结果.

使用标准promisise readFile()

首先,让我们“承诺”您的readFile操作,以便随后可以使用promise逻辑来控制事物.

function readFile(file) {
    return new Promise(function(resolve, reject) {
        var reader = new FileReader();
        reader.onload = function(e) {
            resolve(e.target.result);
        };
        reader.onerror = reader.onabort = reject;
        reader.readAsBinaryString(file);
    });
}

遵循标准承诺,所有操作并行

要并行运行所有文件操作并按顺序返回所有结果并使用标准的Promise,可以执行以下操作:

function readmultifiles(files) {
    return Promise.all(files.map(readFile));
}

// sample usage
readmultifiles(arrayOfFiles).then(function(results) {
    // all results in the results array here
});

遵循标准承诺,所有操作按顺序进行

要按顺序运行所有文件操作(尽管您的原始代码对它们进行了排序,但似乎所有操作都是独立的,因此似乎不需要执行此操作)并按顺序返回所有结果并使用标准的Promise.这个.

这种用于排序的标准设计模式使用.reduce()遍历数组并将所有操作链接在一起,以便它们在链的顺序中一次运行一次:

function readmultifiles(files) {
    var results = [];
    files.reduce(function(p, file) {
        return p.then(function() {
            return readFile(file).then(function(data) {
                // put this result into the results array
                results.push(data);
            });
        });
    }, Promise.resolve()).then(function() {
        // make final resolved value be the results array
        return results;
    });
}

// sample usage
readmultifiles(arrayOfFiles).then(function(results) {
    // all results in the results array here
});

而且,这是使用jQuery Promise的外观

使用jQuery Promisise readFile():

function readFile(file) {
    return new $.Deferred(function(def) {
        var reader = new FileReader();
        reader.onload = function() {
            def.resolve(e.target.result);
        };
        reader.onerror = reader.onabort = def.reject;
        reader.readAsBinaryString(file);
    }).promise();
}

与jQuery并行运行:

function readmultifiles(files) {
    return $.when.apply($, files.map(readFile));
}

// sample usage
readmultifiles(arrayOfFiles).then(function() {
    var results = Array.prototype.slice(arguments);
    // all results in the results array here
});

并且,要与jQuery顺序运行

function readmultifiles(files) {
    var results = [];
    files.reduce(function(p, file) {
        return p.then(function() {
            return readFile(file).then(function(data) {
                // put this result into the results array
                results.push(data);
            });
        });
    }, $.Deferred().resolve()).then(function() {
        // make final resolved value be the results array
        return results;
    });
}

// sample usage
readmultifiles(arrayOfFiles).then(function(results) {
    // all results in the results array here
});

蓝鸟实施

而且,为完整起见,我将向您展示使用more advanced promise library like Bluebird小巧的外观,其中包含一些有用的附加功能.并行代码和readFile()的实现与标准Promise相同,但是对于顺序实现,它可以利用一些内置的Bluebird操作对异步操作进行排序,并且它仅包括:

function readmultifiles(files) {
    return Promise.mapSeries(files, readFile);
}

// sample usage
readmultifiles(arrayOfFiles).then(function(results) {
    // all results in the results array here
});
上一篇:Python中的嵌套Lambda


下一篇:kubeadm安装k8s