如何确定已读取所有文件并解决承诺 [英] How to determine that all the files have been read and resolve a promise

查看:88
本文介绍了如何确定已读取所有文件并解决承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The following code is responsible for reading files. My requirement is how to find whether all files has been read so that I can return or resolve a promise from the parent function(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);
            }
        }

推荐答案

在一个好的设计中,要考虑到您的实现可以从中学习的承诺,其中有几件事情需要考虑:

There are several things to consider in a good design using promises that your implementation could learn from:

  1. 从最低级别的异步操作中创建承诺(称为承诺").然后,您可以使用promise功能来控制逻辑流并传播错误,并且可以用promise一致地实现您的代码.在这种情况下,这意味着您应承诺readFile().它还使readFile()在您的项目或将来的项目中的其他地方更加有用.
  2. 确保始终正确传播错误.使用异步代码(不使用promise时),可能很难正确地将错误返回给原始调用者,尤其是如果异步逻辑最终变得复杂(使用嵌套或序列操作).
  3. 请仔细考虑您的异步操作必须是序列还是它们可以并行运行.如果一个操作不依赖于另一个操作,并且您不太可能因多个请求而使某些服务过载,那么并行运行事物通常会更快地达到结果.
  4. 从异步函数返回承诺,以便调用者可以知道何时完成操作并可以访问异步结果.
  5. 不要不必要地围绕现有的承诺创建另一个承诺(被视为承诺反模式之一).
  6. 如果使用jQuery Promise,请尝试坚持与Promise标准兼容的jQuery功能,这样您就不会遇到将来的互操作性问题,也不会使将来的代码读者更可能知道标准Promise是如何工作的.
  1. Create a promise (called "promisify") from the lowest level async operation your have. Then, you can use promise features to control the logic flow and propagate errors and your code will be consistently implemented with promises. In this case, it means you should promisify readFile(). It also makes readFile() more useful elsewhere in your project or in future projects.
  2. Make sure you are always propagating errors properly. With async code when not using promises, it can be hard to properly get errors back to the original caller, particular if the async logic ends up complicated (with nested or sequences operations).
  3. Consider carefully whether your async operations must be sequences or whether they can run in parallel. If one operation does not depend upon another and you aren't likely to overload some service with multiple requests, then running things in parallel will often achieve a result quicker.
  4. Return promises from async functions so callers can know when things are done and can access async results.
  5. Don't create another promise around an existing promise unnecessarily (considered one of the promise anti-patterns).
  6. If using jQuery promises, try to stick to jQuery features that are compatible with the promise standard so you don't run into interoperability issues going forward or confuse future readers of your code who are more likely to know how standard promises work.

鉴于所有这些,以下是五种实现代码的方法-使用标准的Promise,使用jQuery Promise和您的操作序列或并行运行以及使用Bluebird Promise.在所有情况下,您最终都会获得一个按顺序排列的结果数组.

Given all that, here are five ways to implement your code -using standard promises, using jQuery promises and with your operation sequences or run in parallel and using Bluebird promises. In all cases, you get an array of results in order at the end.

使用标准承诺承诺readFile()

Promisify readFile() using standard promises

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

First, let's "promisify" your readFile operation so you can then use promise logic to control things.

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,可以执行以下操作:

To run all your file operations in parallel and return all the results in order and use standard promises, you can do this:

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

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

具有标准的承诺,所有操作按顺序进行

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

To run all your files operations in sequence (which it does not look like you need to do here because all the operations are indepedent even though your original code was sequencing them) and return all the results in order and use standard promises, you can do this.

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

This, somewhat standard design pattern for sequencing uses .reduce() to sequence through the array and chain all the operations together so they are run one at a time down the sequence of the chain:

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的外观

And, here's how it would look using jQuery promises

使用jQuery Promise承诺readFile():

Promisify readFile() using jQuery promises:

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
});

Bluebird实施

为了完整起见,我将使用一些更高级的承诺向您展示它的外观像Bluebird 这样的库,它具有在此处有用的附加功能.并行代码和readFile()的实现与标准Promise相同,但是对于顺序实现,它可以利用一些内置的Bluebird操作对异步操作进行排序,并且只需包含以下内容即可:

And, for completeness, I'll show you what it looks like using a little more advanced promise library like Bluebird that has additional capabilities that are useful here. The parallel code and the implementation of readFile() is the same as for standard promises, but for the sequential implementation, it could take advantage of some built-in Bluebird operations for sequencing async operation and it would just consist of:

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

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

这篇关于如何确定已读取所有文件并解决承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆