0

我注意到一些在 [].map 之后使用 try/catch 块进行引用的方式确实有延迟。我想知道为什么以及如何避免这种行为?

我的测试用例是:

-file_picked 是 type=file 的输入更改事件的处理程序

    file_picked: function(e){

        var flist = e.target.files, //all picked files
            parsed = [],        //all ok read
            errors = [];        //all errored

        //parse files
        _.map(flist, function(file){
            var reader = new FileReader();
            //set callbacks
            reader.onload = function(e){    //@reading done
                try{
                    var file_cont = e.target.result,
                        parser = new(less.Parser)({
                            filename: file.name
                        });
                    //run file through the less parser
                    parser.parse(file_cont, function (err, tree) {  //parser done
                        var o = {};
                        if (err) {  //@some parser error occured
                            err('less parser error',err);
                            o[file.name] =  err;
                            errors.push(o);
                        }else{  //@parsed successfully by the less parser
                            o[file.name] =  tree.toCSS();
                            parsed.push(o);
                        }
                    });
                }catch(e){
                    err('reader onload exception',arguments);
                    var o = {}; o[file.name] =  i18n('Parsing failed');
                    errors.push(o);
                }
            };
            reader.onerror = function(e){   //@reading error
                err('reader onerror',arguments);
                var o = {}; o[file.name] =  i18n('Reading failed with error: ')+e.target.error.code;
                errors.push(o);
            };
            //start reading
            reader.readAsText( file );
        });

        //reading completed
            console.log(parsed) 
            for( var i = 0; i < parsed.length; i++ ) {
            console.log(parsed[i],errors);
        }           
    }

我在控制台中看到了解析后的数组!但它永远不会被迭代,为什么?

提前致谢

PS.:_.map 是 underscore.js 方法,err,lg 只是 console.xxx 包装器。

4

2 回答 2

0

map函数是同步的,但在您传递给该map函数的回调函数中,您正在执行异步操作。

reader.readAsText( file );是异步的。

这意味着map函数在任何数据被附加到parsed数组之前返回。onload一个简单的解决方法是通过在和onerror回调中添加计数器来跟踪已处理的文件数量。当已处理的文件数量达到flist.length时,您将调用一个函数来完成这项工作parsed

于 2013-09-03T15:00:00.863 回答
0

您可以通过这种方式执行此操作,以便遍历已解析文件的函数仅在所有异步调用完成后运行:

_.wrap 在被调用 n 次后运行一个函数,在你的情况下是 flist.length

[file_picked: function(e){

    var flist = e.target.files, //all picked files
        parsed = [],        //all ok read
        errors = [\],
        readParsed;        //all errored

    //parse files
    _.map(flist, function(file){
        var reader = new FileReader();
      //set callbacks
        reader.onload = function(e){    //@reading done
            try{
                var file_cont = e.target.result,
                    parser = new(less.Parser)({
                        filename: file.name
                    });
                //run file through the less parser
                parser.parse(file_cont, function (err, tree) {  //parser done
                    var o = {};
                    if (err) {  //@some parser error occured
                        err('less parser error',err);
                        [file.name] =  err;
                        errors.push(o);
                    }else{  //@parsed successfully by the less parser
                        [file.name] =  tree.toCSS();
                        parsed.push(o);
                    }

                    readParsed();
              });
            }catch(e){
                err('reader onload exception',arguments);
                var o = {}; [file.name] =  i18n('Parsing failed');
                errors.push(o);
                readParsed();
            }
        };

        reader.onerror = function(e){   //@reading error
            err('reader onerror',arguments);
            var o = {}; o\[file.name\] =  i18n('Reading failed with error: ')+e.target.error.code;
            errors.push(o);

            readParsed();
        };
        //start reading
        reader.readAsText( file );
    });

    readParsed = _.after(flist.length, function(){
        console.log(parsed);

        for( var i = 0; i < parsed.length; i++ ) {
            console.log(parsed[i],errors);
        }
    });
}][1]
于 2013-09-03T15:00:44.653 回答