Как сохранить порядок объектов в Parse.com/backbone.js
-
13-12-2019 - |
Вопрос
У меня есть список папок, принадлежащих пользователю, и я хочу, чтобы он мог изменять их порядок путем перетаскивания.Я могу заставить перетаскивание работать нормально, но не могу понять, как сохранить результаты.Я использую Parse и думаю, это означает, что мне нужно получить каждый объект, изменить атрибут порядка, а затем повторно сохранить его...но, похоже, это не работает, поскольку все они выходят в одном и том же порядке.
После сортировки и выполнения .sortable('toArray') у меня есть массив идентификаторов папок, к которому добавляется слово "папка", поэтому он выглядит примерно так: ["folder_ab9gu3nd", "folder_kwkgiutyqo", "folder_s856skt8w"].
Итак, я хочу сохранить папку ab9gu3nd с порядком 0, kwkgiutyqo с порядком 1 и s856skt8w с порядком 2.
Вот мой код («результат» — это массив с идентификаторами папок):
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.Как мне предотвратить это?Спасибо!
Решение
Вас обманывают две вещи:
- Твой
var
внутри цикла передаются в окружающую функцию, они не являются локальными для цикла. - Твой
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
будет иметь последнее значение из цикла;последнее значение в вашем случае равно двум.
Чтобы решить вашу проблему, вам просто нужно получить отдельный 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);
Какой подход вы выберете, зависит от ваших личных предпочтений.