2015-08-23 6 views
0

Я новичок в использовании узла js, поэтому очень вероятно, что я неправильно понимаю понятие «обещание» и «обратный ад». В любом случае, мне нужно предложения о том, как избежать следующего кода:Остановить продолжение цепочки обещаний без вызова ада

var Sequelize = require('sequelize'); 
var DB = new Sequelize('project1db', 'john', 'password123', { 
    host: 'localhost', 
    dialect: 'mysql' 
}); 


var DB_PREFIX = 't_'; 

DB.query(
'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'user` (' + 
'`user_id` int(11) UNSIGNED NOT NULL' + 
') ENGINE=InnoDB DEFAULT CHARSET=utf8;',{type: DB.QueryTypes.RAW}) 
.then(function(results) { 
    DB.query(
    'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'organization` (' + 
    '`organization_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT ' + 
    ') ENGINE=InnoDB DEFAULT CHARSET=utf8; ', {type:DB.QueryTypes.RAW}) 
    .then(function(results) { 
     DB.query(
     'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'user_organization` (' + 
     '`user_id` int(11) UNSIGNED NOT NULL ' + 
     ') ENGINE=InnoDB DEFAULT CHARSET=utf8; ') 
     .then(function(){ 
      DB.query(
      'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'content` (' + 
      '`content_id` int(11) UNSIGNED NOT NULL ' + 
      ') ENGINE=InnoDB DEFAULT CHARSET=utf8; ', {type:DB.QueryTypes.RAW}) 
      .then(function(){ 
      // more queries 
      }).catch(function(err){console.log(err);}); 
     }).catch(function(err){console.log(err);}); 
    }).catch(function(err){console.log(err);}); 
}).catch(function(err){console.log(err);}); 

игнорировать тот факт, что я создаю таблицы с SQL вместо использования сценариев миграции Sequelize, потому что я просто пытаюсь показать точку что у меня есть много запросов mysql, которые должны запускаться последовательно. Если запрос завершается с ошибкой, мне нужно остановить весь скрипт и не дать ему активировать функцию .then(). В моем коде Sequelize я достиг этого, вложив множество вызовов функций необработанных запросов, а затем и catch. Это будет очень сложно устранить, если у меня есть 100 из этих вложенных операторов обратного вызова.

Есть ли альтернативы для меня, чтобы учесть все эти функции обратного вызова?

+0

Кажется, что вы можете поместить все эти запросы в массив, а затем просто использовать одну функцию для каждого из них по одному, останавливаясь при возникновении ошибки. – jfriend00

+0

@ jfriend00, если вы предлагаете приведенный ниже ответ robertklep, я попробовал это, но столкнулся с проблемой, когда последующие функции '.then()' продолжали запускать после ошибочного запроса в рамках одной из функций .then(). Я пытаюсь выяснить, как остановить поток '.then()' function from firing – John

ответ

1

Sequelize использует (модифицированную версию) Библиотеку bluebird обещает, что означает, что это должно работать:

var Promise = Sequelize.Promise; 

Promise.each([ 
    'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'user` (' + 
    '`user_id` int(11) UNSIGNED NOT NULL' + 
    ') ENGINE=InnoDB DEFAULT CHARSET=utf8;', 
    'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'organization` (' + 
    '`organization_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT ' + 
    ') ENGINE=InnoDB DEFAULT CHARSET=utf8; ', 
    'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'user_organization` (' + 
    '`user_id` int(11) UNSIGNED NOT NULL ' + 
    ') ENGINE=InnoDB DEFAULT CHARSET=utf8; ', 
    'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'content` (' + 
    '`content_id` int(11) UNSIGNED NOT NULL ' + 
    ') ENGINE=InnoDB DEFAULT CHARSET=utf8; ', 
], function runQuery(query) { 
    return DB.query(query, { type: DB.QueryTypes.RAW }); 
}).then(function() { 
    console.log('all done'); 
}).catch(function(err) { 
    console.log(err); 
}); 

Он использует статическую версию .each(), которая будет перебирать элементы массива последовательно проходят каждый к итератору runQuery (который возвращает обещание), и остановится, когда обещание будет отклонено.

+0

Я пробовал ваш скрипт. Я преднамеренно вызвал синтаксическую ошибку в инструкции create organization table, и хотя узел сообщил об ошибке, он все равно продолжал итерацию через оставшиеся сборки user_organization и content table. Есть ли что-то, что я могу сделать, чтобы отвергнуть обещание остановить продолжение каждого цикла? – John

+0

Мне также пришлось изменить 'var Promise = sequelize.Promise;' to 'var Promise = Sequelize.Promise;' чтобы все работало. – John

+0

@ Ион итерации Джона должен прекратиться, когда запрос не удался (что я могу воспроизвести с помощью драйвера SQLite). Однако, если драйвер MySQL использует транзакции, пул соединений или какой-то механизм задержек запросов (где ошибки запроса не выбрасываются немедленно), это может завершиться неудачей. Однако в этом случае вам, вероятно, придется изменить настройки драйвера. – robertklep

0

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

Если вам нужны последовательные SQL-команды, вы все равно можете сделать это в пределах 1 команды. В любом случае запрос будет выполняться последовательно. Если вы хотите, чтобы каждая отдельная таблица была моделью, создайте сценарии миграции для этой модели, не делайте этого так.