Как я могу вернуть данные из обещания?

Работа с NodeJS . Я создал базу данных в SQLite (не путать с SQLite3 ) и хочу проверить, есть ли у пользователя определенный диапазон.

msg.member.roles.has (rows.moderator);

Однако я сталкиваюсь с новой проблемой, возвращающей значение из обещания. Код выглядит следующим образом:

var sql = require('sqlite');
bot.elevation = function(msg) {
  let permlvl = 0;
  sql.open('guildconfig.db').then(() => {
    sql.get(`SELECT * FROM config WHERE id = '${msg.guild.id}'`).then(rows => {
      if (!rows) {
        sql.run('INSERT INTO config (id) VALUES (?)', [`${msg.guild.id}`]);
        if (msg.member.hasPermission("MANAGE_MESSAGES")) permlvl = 1;
        if (msg.member.hasPermission("ADMINISTRATOR")) permlvl = 2;
      } else {
        if (msg.member.roles.has(rows.moderator)) permlvl = 1;
        if (msg.member.roles.has(rows.administrator)) permlvl = 2;
        // return permlvl;
      }
    })
  });
  if (msg.author.id === msg.guild.owner.id) permlvl = 3;
  if (msg.author.id === '242043489611808769') permlvl = 10;
  return permlvl;
};

Что я хочу сделать, это вернуть значение permlvl, которое находится в пределах .then, как я могу это сделать?

1
задан 11.01.2017, 00:13
0 ответов

Используя chaining обещаний, ты был бы должен мочь делать это так:

var sql = require('sqlite');
bot.elevation = function (msg) {

  if (msg.author.id === msg.guild.owner.id) {
    return Promise.resolve(3);
  }

  if (msg.author.id === '242043489611808769') {
    return Promise.resolve(10);
  }

  // Return a Promise
  return Promise.resolve()
    .then(() => sql.open('guildconfig.db', { Promise }))
    .then(() => sql.get('SELECT * FROM config WHERE id = ?', msg.guild.id))
    .then(rows => {
      let permlvl;

      if (!rows) {
        sql.run('INSERT INTO config (id) VALUES (?)', msg.guild.id);
        if (msg.member.hasPermission("MANAGE_MESSAGES")) {
          permlvl = 1;
        }
        else if (msg.member.hasPermission("ADMINISTRATOR")) {
          permlvl = 2;
        }
      } else  if (msg.member.roles.has(rows.moderator)) {
        permlvl = 1;
      }
      else if (msg.member.roles.has(rows.administrator)) {
          permlvl = 2;
      }

      return permlvl;
    });
};

Пример использования:

bot.elevation(msg)
  .then(lvl => { console.log(lvl); });
1
ответ дан 03.12.2019, 17:46

Есть две формы, не используя callbacks:

  • Используя promise chaining
  • Используя async/await

Promise chaining

Техническая состоит в сцеплении обещаний, таким образом что стоимость смогла оставаться mutando через эти.

bot.elevation = function (msg) {
  return sql.open('guildconfig.db')
    .then(() => {
      return sql.get(...)
    })
    .then(rows => {
      ... // revisar permisos
      return permlvl;
    });
};

Так, когда ты позвонишь в bot#elevation ты получишь новое обещание со стоимостью последнего укрытого обещания.

Async/Await

Это новая форма, чтобы обрабатывать информацию с асинхронным программированием и обещаниями в общем. Посредством await мы можем "надеяться" на то, что обещание заканчивает Ваше выполнение.

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

bot.elevation = async function (msg) {
  await sql.open('guildconfig.db');
  let rows = await sql.get(...);
  let permlvl;

  if (!rows) {
    await sql.run(...);
    ...
  } else {
    ...
  }
  return permlvl;
}

И ты это использовал бы этой форму:

(async () => {
  let permlvl = await bot.elevation({ ... });
})();
2
ответ дан 03.12.2019, 17:46

Код остался бы что-либо подобное, также модуля в nodejs, что делает синхронные консультации в sqlite https://www.npmjs.com/package/sqlite-sync

bot.elevation = function(msg, callback) {
  let permlvl = 0;
  sql.open('guildconfig.db').then(() => {
    sql.get(`SELECT * FROM config WHERE id = '${msg.guild.id}'`).then(rows => {
      if (!rows) {
        sql.run('INSERT INTO config (id) VALUES (?)', [`${msg.guild.id}`]);
        if (msg.member.hasPermission("MANAGE_MESSAGES")) permlvl = 1;
        if (msg.member.hasPermission("ADMINISTRATOR")) permlvl = 2;
      } else {
        if (msg.member.roles.has(rows.moderator)) permlvl = 1;
        if (msg.member.roles.has(rows.administrator)) permlvl = 2;
      }
      if (msg.author.id === msg.guild.owner.id) permlvl = 3;
      if (msg.author.id === '242043489611808769') permlvl = 10;
      callback(permlvl);
    });
  });
  // return permlvl;
};

bot.elevation(msg, function(permlvl){
    console.log(permlvl);
});
1
ответ дан 03.12.2019, 17:46

Из-за твоего вопроса и последующих дискуссий, которые я читаю в остальных ответах, я вижу, что они исходят из очень основной концепции, которую им даже не ясно, Javascript - функциональный асинхронный язык, любая операция I/O в javascript будет являться всегда асинхронным, это не зависит от базы данных или API, которые использовали бы, чтобы реализовывать эти операции, это природа языка и весь Ваш API всегда будет справляться с callbacks или promises.

Sqlite, Sqlite3, Mongo, Redis, Постглинистый песчаник и остальные существующие BD и из-за того, что существует, они не являются асинхронными, одинокий базы данных, если ты хочешь согласиться на них используя Java например тогда, все вызовы I/O, которые Java реализует в эти базы данных, будут являться синхронными, bloqueantes и повелительными.

Наоборот, если они используют Javascript тогда, API's, чтобы соглашаться на те же базы данных, будут являться всегда асинхронными и функциональными поэтому не bloqueantes.

Чтобы бороться с асинхронным выполнением в Javascript у тебя есть всегда 2 модели, callbacks и promises.

В Javascript ты можешь перемещать функцию как параметр или стоимость, потому что функции в Javascript - объекты первого порядка, это - то, что позволяет тебе перемещать код как параметр, вышеупомянутый код может быть выполненным в другой точке приложения, в то время как последовательность главного выполнения может продолжать в следующие инструкции эта функция - та, которая позволяет тебе осуществлять callbacks.

Столько callbacks, как promises они асинхронные, - что-то неизбежное включено, если ты используешь async/await в финале, ты будешь должен бороться с асинхронным выполнением, чтобы бороться с выполнением того асинхронного кода и выполнять серийным способом асинхронный код, у тебя будет два выбора:

  • вложение в случае callbacks
  • и promise chaining в случае promises

Я не размещу специфический код использования API SQLite, так как важной является концепция, это применяется во всех книжных магазинах, которые ты находишь в Javascript

Это вложение callbacks

SQliteDAO.getCliente(1, function(error, cliente){
  if(error){
    throw 'Error al obtener el cliente:' + error.msg;
  } else {
    SQliteDAO.getPermisos(cliente.id, function(error, permisos){
      if(error){
        throw 'Error al obtener permisos:' + error.msg;
      } else {
        permisos.forEach(function(permiso){
        console.log('Permiso: ' + permiso);
      })
      }
    })
  }
})

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

Также заметь, как, укрыв все callbacks, код становится все более тяжелым для того, чтобы читать и ему должен контроль ошибок их в каждом callback.

Сейчас с promises это было бы таким.

SQLiteDAO.getCliente(1)
  .then(cliente => return SQLiteDAO.getPermisos(cliente.id))
  .then(permisos => permisos.forEach(permiso => console.log('Permiso: ' + permiso)))
  .fail(error => console.log('Error: ' + error.msg));

С promises ты делаешь то же самое, контролируешь разгрузку выполнения асинхронного кода, но не используешь вложение а method chaining (техника, которая не изобретение promises), promises всегда возвращают стоимость, которая может быть новым promise или стоимостью с конечным результатом и также может возвращать ошибку, преимущество состоит в том, что ошибка могут пропагандировать в весь chain и захватывать это в конце chain по этой причине ты не нуждаешься в том, чтобы захватить ошибку после каждого выполнения промежуточного promise и можешь захватывать это в конце концов, это преимущество method chaining.

С promises код более натурален, легок для того, чтобы быть прочитанным и помогает тебе для того же намерения, что и укрытые callbacks, но Ваше использование проще, представляет быть должное делать 10 асинхронных вызовов укрывая 10 callbacks в отличие от сцепления promises и захватывания любой ошибки в конце концов.

Поскольку ты видишь, это два различных способа делать то же самое, есть многие другие технические детали осуществления promises например внутри они используют callbacks, что всегда получают два параметра, 'ошибку' и 'ответ' function (err, он восходит), большинство старых API's, которые не используют promises а callbacks они используют callbacks формы function (err, он восходит), это позволяет, что эти же самые API's смогли быть преобразованными в promises, ты можешь видеть это здесь.

Эти два главных файла ты будешь находить всегда в Javascript, сейчас с прогрессом async/await в случае promises, но всегда ты будешь бороться с асинхронным кодом и все API's, которых ты используешь, предложат тебе один или обе техники программирования.

0
ответ дан 03.12.2019, 17:46