2015-12-14 4 views
0

Я полагаю, что это связано с асинхронностью Javascript или чем-то подобным. Я только что прочитал о обещаниях и подумал, что это может решить мою проблему, но пока этого не произошло. В любом случае, вот фрагмент кода и то, что Im стремится достичь с ним:Итерация по нескольким классам (таблицам) parse.com и извлечению запросов

Сценарий: я хотел бы запросить 10 таблиц и получить последние сообщения (для этого примера, 1 сообщение) и сохранить это в словарь формата

<Class Name> : <Obj Id> 

ниже фрагмент кода выполняет следующие действия, или пытается сделать следующее:

  1. построить массив с именем activeTables, который содержит список таблиц для запросов. Этот массив сам хранятся в отдельной таблице под названием Config
  2. Для каждого элемента массива activeTable, выполнить запрос по этому пункту, для последнего пункта и добавить его в словарь

Кажется просто, но вот результат Im получаю:

Предполагая, что мы бежим это на 3-х таблицах, называемых Table_1, Table_2, Table_3 и самые последние OBJS на каждой таблице: recent_1, recent_2, recent_3 соответственно, что я вижу на NewList это:

newlist = { 
    "Table_1" : ["recent_1", "recent_2", "recent_3"] 
} 

вместо:

newlist = { 
    "Table_1" : ["recent_1"], 
    "Table_2" : ["recent_2"], 
    "Table_3" : ["recent_3"], 
} 

и он бьет меня, что в то время как я был в состоянии запросить 3 таблицы и получить самую последнюю запись, только при вставке его в словарь, он отказывается, чтобы добавить новый ключ для каждой таблицы , если существует один ключ

(Кроме того, я использую обещания неправильно? Так как я все еще вижу знакомую пирамиду обратного вызова ад)

Фрагмент кода ссылки выше:

Parse.Cloud.job("scanLists", function(request, status) { 
    var activeTables = []; 
    var getclass = Parse.Object.extend("Config"); 
    var query = new Parse.Query(getclass); 
    query.equalTo("Name", "ActiveTablesConfigObj"); 
    query.find().then(function(activetables_obj) { 
    var newlist = {}; 
    activeTables = activetables_obj[0].get("cObject").Active.slice(); 
    for (var i = 0; i < activeTables.length; i++) { 
     var t_name = activeTables[i];   
     var get_atc = Parse.Object.extend(t_name); 
     var query_newlist = new Parse.Query(get_atc); 
     query_newlist.descending("createdAt"); 
     query_newlist.find().then(function (newlist_obj) { 
     if (newlist.t_name === undefined) { 
      newlist[t_name] = [newlist_obj[0].id]; 
     } else { 
      newlist[t_name].push(newlist_obj[0].id); 
     } 
     }); 
    } 
    }); 
}); 

ответ

0

Мы можем улучшить код несколькими способами. (1) Создавайте меньшие функции, возвращающие обещания, (2) используйте query.first() вместо find(), когда нам нужен только один результат. Чтобы проиллюстрировать эти две точки, вот функция, которая возвращает обещание, чтобы получить первый «Config» объект:

function getConfig() { 
    var query = new Parse.Query("Config"); 
    query.equalTo("Name", "ActiveTablesConfigObj"); 
    return query.first(); 
} 

Это выглядит, позже в коде, вы хотите, чтобы получить самый новый объект данного класса , Heres' краткая функции для этого:

function newestInstanceOf(klass) { 
    var query = new Parse.Query(klass); 
    query.descending("createdAt"); 
    return query.first(); 
} 

Вот хитрая часть (и часть, которая больше всего нуждается в фиксации в вашем решении) ... query.first() и .find() выполняется асинхронно. Ваш код содержит цикл for, который генерирует несколько обещаний, которые завершаются только после возвращения функции.Не уверен, что ваш фактический код выглядит, но вот как сделать это правильно, собирая обещания в массиве, затем выполняя их вместе с Promise.when():

_ = require("underscore"); // just a great util for arrays, providing things like map() 

function scanLists() { 
    var newlist = {}; 
    return getConfig().then(function(config) { 
     var activeTables = config.get("cObject").Active; 
     // build an array of promises to get the most recent object in each class 
     var promises = _.map(activeTables, function(klass) { 
      return newestInstanceOf(klass).then(function(newestInstance) { 
       if (!newlist[klass]) { newlist[klass] = []; } 
       newlist[klass].push(newestInstance.id); 
      }); 
     }); 
     return Parse.Promise.when(promises); 
    }).then(function() { 
     return newlist; 
    }); 
} 

Обратите внимание, как все возвращается обещание? Последняя вещь ... назовите это из облачной функции, включая реакцию ответа на вызов/ошибку:

Parse.Cloud.job("scanLists", function(request, response) { 
    scanLists().then(function(newlist) { 
     // do something with newlist, if this involves a promise, then... 
     return someObject.save(); 
    }).then(function(result) { 
     response.success(result); 
    }, function(error) { 
     response.error(error); 
    }); 
} 
+0

Действительно понравилось читать этот дань! Фантастическое резюме и предложения - и многое, чтобы убрать для меня и улучшить качество кода – wrecktangle

0

Решено!

Ответ: Я должен использовать анонимные функции!

Так код ниже устраняет проблему

Parse.Cloud.job("scanLists", function(request, status) { 
    var activeTables = []; 
    var getclass = Parse.Object.extend("Config"); 
    var query = new Parse.Query(getclass); 
    query.equalTo("Name", "ActiveTablesConfigObj"); 
    query.find().then(function(activetables_obj) { 
    var newlist = {}; 
    activeTables = activetables_obj[0].get("cObject").Active.slice(); 
    for (var i = 0; i < activeTables.length; i++) { 
     (function(i) { 
     var t_name = activeTables[i];   
     var get_atc = Parse.Object.extend(t_name); 
     var query_newlist = new Parse.Query(get_atc); 
     query_newlist.descending("createdAt"); 
     query_newlist.find().then(function (newlist_obj) { 
      if (newlist.t_name === undefined) { 
      newlist[t_name] = [newlist_obj[0].id]; 
      } else { 
      newlist[t_name].push(newlist_obj[0].id); 
      } 
     }); 
     })(i); 
    } 
    }); 
}); 
+0

Рад, что у вас это работает, но я не вижу, как это может быть. Код возвращается без фактического создания 'newlist' (из-за отсутствия обработки обещаний find() в цикле for). Кроме того, он должен вызывать success() или error() для параметра статуса (обычно называемого «response»). Как вы собираете доказательства того, что это сработало? – danh

+0

Привет @danh, вот что я вижу по отношению к newlist, но, пожалуйста, дайте мне знать, если что-то явно не так, поскольку я все еще новичок в JS и Parse: newlist делится перед циклом for. Затем он выполняется внутри цикла for, поскольку ключи создаются, если они не существуют, или значение передается в массив, к которому принадлежит ключ. Im мой фактический код, когда я выхожу из цикла for, newlist - это полный словарь с ожидаемым ключом, пара значений, который затем я пишу на другой объект обратно на разбор – wrecktangle

+0

Хорошо. Может быть, причина его работы лучше, чем кажется, что-то в «реальном коде». Я напишу пару мыслей очень быстро, просто чтобы прояснить несколько пунктов в том, что вы разместили. – danh

Смежные вопросы