Arhn - архитектура программирования

Как связать объекты в Sequelize (Node js)?

У меня есть модели User и File в Sequlize. Пользователь может иметь несколько файлов. У меня есть ассоциация db.User.hasMany(db.File, {as: 'Files', ForeignKey: 'userId', ограничения: false});

Я хочу инициировать объект пользователя с несколькими файлами и сохранить его в базе данных.

Я написал следующий код:

 var files = [];

        var file1 = models.File.build();
        file1.name = "JPEG";

        file1.save().then(function () {

        });

        files.push(file1);

        var file2 = models.File.build();
        file2.name = "PNG";

        file2.save().then(function () {

        });

        files.push(file2);


 var newUser = models.User.build();
       newUser.email = email;
 newUser.save().then(function (usr) {

 files.forEach(function (item) {
     newUser.addFile(item);
});

});

Но нашел баг, иногда несколько файлов не ассоциировались с пользователем.

Я нашел (в журналах nodejs) команды (обновление) для установки внешних ключей для этих файлов. Но команды не выполнялись. Внешние ключи (userId) нескольких файлов были пустыми.

Думаю проблема в асинхронных запросах. Как организовать структуру кода, чтобы избежать этой ошибки?


  • почему вы не создаете файлы после пользователя и не добавляете идентификатор пользователя в определение файла? 04.10.2016

Ответы:


1

Проблема именно в том, о чем вы думаете, асинхронном коде.

Вам нужно переместить функции внутри обратных вызовов, иначе код запустится до создания файла.

JavaScript не ждет, прежде чем перейти к следующей строке, поэтому он будет запускать следующую строку независимо от того, завершена она или нет. У него нет смысла ждать, прежде чем двигаться.

Таким образом, вы в основном добавляете что-то, чего еще не существует, потому что оно не ждет сохранения файла, прежде чем двигаться дальше.

Это сработает, просто переместив код внутри обратных вызовов then:

var files = [];

var file1 = models.File.build();
file1.name = "JPEG";

file1.save().then(function () {
    files.push(file1);

    var file2 = models.File.build();
    file2.name = "PNG";

    file2.save().then(function () {
        files.push(file2);

        var newUser = models.User.build();
        newUser.email = email;
        newUser.save().then(function (usr) {
            files.forEach(function (item) {
                newUser.addFile(item);
            });
        });
    });
});

Но это грязно. Вместо этого вы можете связать обещания следующим образом:

var files = [];

var file1 = models.File.build();
file1.name = "JPEG";

file1.save()
  .then(function(file1) {
      files.push(file1);

      var file2 = models.File.build();
      file2.name = "PNG";

      return file2.save();
  })
  .then(function(file2) {
      files.push(file2);

      var newUser = models.User.build();
      newUser.email = email;

      return newUser.save();
  })
  .then(function(newUser) {
       files.forEach(function(item) {
           newUser.addFile(item);
       });
  });

Теперь это немного чище, но все еще немного грязно, а также немного сбивает с толку. Таким образом, вы можете использовать функции генератора вместо этого:

var co = require('co');

co(function*() {
    var files = [];

    var file1 = models.File.build();
    file1.name = "JPEG";

    yield file1.save();
    files.push(file1);

    var file2 = models.File.build();
    file2.name = "PNG";

    yield file2.save();
    files.push(file2);

    var newUser = models.User.build();
    newUser.email = email;
    newUser.save();

    files.forEach(function(item) {
        newUser.addFile(item);
    });
});

Теперь это намного лучше.

Посмотрите внимательно, и вы увидите, что происходит. co принимает функцию генератора, которая в основном является обычной функцией со звездочками *. Это специальная функция, которая добавляет поддержку yield выражений.

Выражения yield в основном ждут вызова обратного вызова then(), прежде чем двигаться дальше, и если обратный вызов then имеет аргумент, он также вернет его.

Итак, вы можете сделать что-то вроде:

var gif = yield models.File.create({
  name: 'gif'
});

вместо:

models.File.create({
  name: 'gif'
}).then(function(gif) {

});

Для этого вам нужно использовать небольшой модуль узла под названием co, хотя всего лишь npm install --save co

04.10.2016
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..