0

我有一个属于用户的文件夹列表,我希望他们能够通过拖放来重新排序。我可以让拖放正常工作,但我不知道如何保存结果。我正在使用 Parse,我认为这意味着我必须检索每个对象,更改 order 属性,然后重新保存它......但这似乎不起作用,因为它们都以相同的顺序出现。

在排序然后执行 .sortable('toArray') 之后,我有一个文件夹 id 数组,前面带有单词 'folder',所以它看起来像 ["folder_ab9gu3nd"、"folder_kwkgiutyqo"、"folder_s856skt8w"]。

所以,我想用命令 0 保存文件夹 ab9gu3nd,用命令 1 保存 kwkgiutyqo,用命令 2 保存 s856skt8w。

这是我的代码(“结果”是具有文件夹 ID 的数组):

        for(var ii=0; ii<result.length; ii++) {
                            // Get actual id
            var folderId = result[ii].replace('folder_', '');
            var folderOrder = ii;
            var folder = Parse.Object.extend("Folder");
            var query = new Parse.Query(folder);
            query.get(folderId, {
                success: function(folder) {
                    // The object was retrieved successfully.
                    folder.set('order', folderOrder);
                    folder.save();
                }
            });
        }

当我运行它时,所有文件夹都以“2”的顺序结束,就好像 ii 的最终值用于所有文件夹一样。我该如何阻止这种情况发生?

4

1 回答 1

1

你被两件事愚弄了:

  1. var在循环中的 s 被提升到周围的功能,它们不是循环的本地。
  2. 您的success处理程序是异步触发的,它们是完全相同的folderOrder闭包。

对于第一个,就 JavaScript 而言,您的循环实际上看起来像这样:

function whateverItIsCalled() {
    var folderId, folderOrder, folder, query, ii;
    //...
    for(ii = 0; ii < result.length; ii++) {
        //...
        folderOrder = ii;
        //...
    }
    //...
}

所以folderOrder整个函数只有一个,你的循环只是ii在每次迭代时分配给它。

第二个问题是常见的“循环中的 AJAX”问题:您正在构建一系列匿名函数,这些函数是对同一folderOrder变量的闭包。这样做的结果是所有三个success处理程序最终都引用了相同的folderOrder值,并且在它们被触发时,循环将完成并folderOrder具有循环中的最后一个值;在您的情况下,最后一个值为 2。

要解决您的问题,您只需将单独folderOrder的值放入各种success处理程序中。一种方法是使用函数来生成成功处理程序:

function makeSuccess(folderOrder) {
    return function(folder) {
        folder.set('order', folderOrder);
        folder.save();
    }
}

进而:

query.get(folderId, {
    success: makeSuccess(folderOrder)
});

另一种常见的方法是使用自执行函数来有效地为循环体创建一个不同的范围:

for(var ii = 0; ii < result.length; ii++)
    (function(ii) {
        // Same stuff you currently have...
    })(ii);

您采用哪种方法是个人喜好问题。

于 2012-10-03T20:13:44.330 回答