【问题标题】:Clearing previous dragged file entries?清除以前拖动的文件条目?
【发布时间】:2014-03-15 05:37:19
【问题描述】:

我有以下脚本用于上传文件。它工作正常,但是我很难找出为什么每次我上传一个新文件时,之前拖动的文件也存在。由于程序的异步特性,我无法调试它。

小提琴:

http://jsfiddle.net/tekky/PYTBw/

代码:

var dndbox = $(".dndbox")[0];

dndbox.addEventListener("dragenter", function(e) {
    e.stopPropagation();
    e.preventDefault();
},false);

dndbox.addEventListener("dragover", function(e) {
    e.stopPropagation();
    e.preventDefault();
},false);

dndbox.addEventListener("drop", function(e) {
    e.stopPropagation();
    e.preventDefault();

    var itemList = e.dataTransfer.items;

    var fp = [];

    var traverse = function(entry)
        {
            if (entry.isFile) {
                entry.file(function(file) {
                    var filepromise = new Promise(function(res, rej) {
                        res(file);
                    });
                    fp.push(filepromise);
                });
            } else if (entry.isDirectory){
                var dR = entry.createReader();
                dR.readEntries(function(entries) {
                    for(var i = 0; i < entries.length; i++)
                    {
                        traverse(entries[i]);
                    }
                });
            }
        }

        var collection = [];
        for(var i = 0; i < itemList.length; i++) {
            var e = itemList[i].webkitGetAsEntry();
            var tp = new Promise(function(r, rj) {
                traverse(e);
                r(fp);
            });
            collection.push(tp);
        }

        Promise.all(collection).then(function(ff) {
            $(".prompt").show();
            $(".prompt").on("click", function() {
                $(this).hide();
                ff.forEach(function(pa) {
                    pa.forEach(function(p){
                        p.then(function(f)
                        {
                            console.log(f);
                        });

                    });
                });
            });
        });
},false);

【问题讨论】:

    标签: javascript google-chrome drag-and-drop promise


    【解决方案1】:

    每次我上传新文件时,之前拖动的文件也会出现。

    这不是由于 traverse 的异步特性,并且与 Promise 没有太大关系。这是由于这种结构:

    // left away some irrelevant callbacks
    dndbox.addEventListener("drop", function(e) {
        var fp = [];
        // add entries to fp
        $(".prompt").on("click", function() {
            console.log(fp);
        });
    }, false);
    

    如您所见,每次删除某些内容时,您都会创建一个新列表并为(相同的)元素添加一个监听器,从现在开始每次点击都会记录该列表。要解决这个问题,您可以:

    • 仅使用一个全局列表,在发生新的放置事件时将被覆盖
    • 为每个要记录的列表创建一个新的.prompt 元素
    • 在监听器触发后卸载它,这样它就不会再次被触发。为此,您可以使用 jQuery .one() method

    除此之外,您还非常奇怪地使用了 Promises(不是说错了)。 collection 是一个 Promise 列表,这些 Promise 立即被仍然为空的 fp 数组解决。只有当触发click 回调时所有文件都被读入,你才幸运。尽管如此,每个pa 都会得到=== fp,因此您在fp 中记录每个项目的次数与itemList 的长度一样多。

    查看Understanding promises in node.js for recursive functionIs there an example of using raw Q promise library with node to recursively traverse a directory asynchronously? 以了解如何正确执行此操作。在你的情况下,就像

    function traverse(entries)
        var collection = [];
        for (var i=0; i<entries.length; i++) {
            var entry = entries[i];
            if (entry.isFile) {
                collection.push(new Promise(function(res, rej) {
                    entry.file(res);
                }));
            } else if (entry.isDirectory){
                collection.push(new Promise(function(res, rej) {
                    var dR = entry.createReader();
                    dR.readEntries(res);
                }).then(traverse));
            }
        }
        return Promise.all(collection).then(function(results) { // flatten
            return [].concat.apply([], results);
        });
    }
    
    var entries = [];
    for(var i = 0; i < itemList.length; i++)
        entries[i] = itemList[i].webkitGetAsEntry();
    
    traverse(entries).then(function(fp) {
        $(".prompt").show().one("click", function() {
            $(this).hide();
            fp.forEach(console.log, console);
        });
    });
    

    【讨论】:

    • 哇...谢谢。这看起来是一件很头疼的事。我理解它,但我觉得我需要很长时间才能弄清楚。我想我只需要习惯使用 Promise。这是我第一次需要这么多。我希望我可以用一些比特币/狗狗币之类的东西给你小费!再次,非常感谢!
    猜你喜欢
    • 2012-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-06
    • 2011-06-01
    相关资源
    最近更新 更多