sqlite3 - обещание асинхронных вызовов

1

Я хочу выбрать асинхронные данные базы данных sqlite3. Но поскольку db.each является асинхронной функцией, моя следующая функция select работает неправильно. Как добавить обещание подождать результата?

const sqlite3 = require('sqlite3').verbose();

export default function select(database, table) {
  return new Promise((resolve, reject) => {
    const db = new sqlite3.Database(database);
    const queries = [];
    db.each('SELECT rowid as key, * FROM ${table}', (err, row) => {
      if (err) {
        reject(err);
      }
      console.log('Push row ${row.key} from database.');
      queries.push(row);
    });
    console.log(queries);
    console.log(JSON.stringify(queries));
  });
}

Изображение 174551

Теги:
sqlite3
asynchronous
promise

1 ответ

2
Лучший ответ

db.each() требует немного громоздкого, нестандартного обещания из-за характера его обратных вызовов, через которые он:

  • поставляет строки по одному, к первому обратному вызову,
  • завершение сигнала до второго обратного вызова.

Сравните это со стандартным шаблоном, выставленным в db.all(), который принимает один обратный вызов с сигнатурой (err, rows).

Придерживаясь db.each(), то, что вы написали, правильно, насколько это возможно, но не позволяет решить обещание по завершении db.each().

К счастью, решение, несмотря на громоздкость, довольно просто. resolve(queries) можно вызвать из второго обратного вызова.

export default function select(database, table) {
    return new Promise((resolve, reject) => {
        const db = new sqlite3.Database(database);
        const queries = [];
        db.each('SELECT rowid as key, * FROM ${table}', (err, row) => {
            if (err) {
                reject(err); // optional: you might choose to swallow errors.
            } else {
                queries.push(row); // accumulate the data
            }
        }, (err, n) => {
            if (err) {
                reject(err); // optional: again, you might choose to swallow this error.
            } else {
                resolve(queries); // resolve the promise
            }
        });
    });
}

Если ожидаемое количество строк "очень ограничено" (как сказано в документации SQLite), используйте вместо этого db.all().

  • 0
    Спасибо! Ценить это.
  • 0
    Разве это не приводит к необходимости загрузки всего набора результатов в память, как это делает all() ? У меня нет лучшего решения, я просто относительный JS n00b, и я пытаюсь понять, как эффективно использовать память с большими наборами результатов.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню