получить асинхронные данные из Rest api и загрузить их в mongodb с помощью node.js - используя обещания - PullRequest
0 голосов
/ 07 октября 2018

Я работал с Javascript не так уж много и сейчас борюсь.

Короче:

Я хочу получить данные из Rest-API и массово вставить их вколлекция работающей базы данных MongoDB.

Насколько мне известно:

Поскольку Javascript является однопоточным языком.Поэтому, если вы хотите, чтобы что-то было сделано после того, как другие вещи были завершены (в основном асинхронные операции), вы должны использовать обратные вызовы. Обратный вызов: Обратный вызов - это функция A , которая передается функции в качестве параметра и должна выполняться в конце внутри этой функции, чтобы гарантировать, что либо A

  • выполняется как последнее действие

или

  • данные / объекты, которые должны были быть получены асинхронно, возможно, доступны, чтобы они могли бытьиспользуется внутри A

Обещания:

Представлена ​​ли сравнительно новая функция в Javascript, которая может использоваться для работы с однопоточным характером Javascript?Обещания имеют разные состояния (выполнено, отклонено, ожидает рассмотрения, выполнено).

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

Мой сценарий:

Это класс с функцией, которая использует 'request' для выполнения REST-запроса.

class DataManager {
    static loadSkill(uri) {
        return new Promise((resolve, reject) => {
            const apiEndpoint = 'apiEndpoint';
            request(apiEndpoint + uri, (error, response, body) => {
                if (!error && response.statusCode === 200) {
                    resolve(body)
                } else reject(error);
            });
        });
    }
 ...
}

В следующей функции я читаю URI данных, которые я хочу получить из файла JSON.Загруженный и проанализированный массив разделен на массивы размером 100 записей, потому что я хочу выполнить массовую вставку сразу 100 объектов.Во внутреннем цикле forEach я пытаюсь загрузить навык, используя обещание с await , поэтому функция должна быть объявлена ​​с async

function retrieveAndInsertAllSkills() {
    //DBManager.createCollection('skills');
    fs.readFile('./data/uris.json', 'utf8', function readFileCallback(err, data) {
        if (err) {
            console.log(err);
        } else {
            let obj = JSON.parse(data);

            let chunks = chunk(obj.uris, 100);

            chunks.forEach((chunk)=>{
                let skills = [];
                chunk.forEach(async (uri) => {
                    let skill = await Datamanager.loadSkill(uri);
                    skills.push(skill);
                });
                DBManager.insertMany(skills,'skills')
            })
        }
    });
}

Atво-первых, я запускаю сообщение об ошибке MongoDB.Но я понял, что ошибка была вызвана попыткой вставить пустые массивы. Итак, если честно, я столкнулся с подобной проблемой при другой проблеме.

Я пытаюсь выполнить команду оболочки Linux (sha1sum [файл]), чтобы получить контрольную сумму.Файлы имеют большой размер, и я

class FileUtil {
    static executeCommand(command, paramsArray) {
        return new Promise((resolve, reject) => {
            let cmd = spawn(command, paramsArray);
            cmd.stdout.on('data', data => {
                resolve(data.toString());
            });
            cmd.stderr.on('data', error => {
                reject(error.toString());
            });
        });
    }
  ...
    static getSha1Sum(file){
        this.executeCommand('sha1sum', [file])
            .then((chkSum) => {
                console.log(chkSum);
                return chSum
            })
            .catch((errorMsg) =>{
                console.log(errorMsg);
                return new Error(errorMsg)});
    };
 ...
}

Следующий код выводит «undefined» только на консоли.Приведенный выше код выводит желаемый результат.

async function testcheck(file) {
    try {
        let hash = await FileUtil.getSha1Sum(file);
        console.log(hash);
    }
    catch (e) {
        console.log(e);
    }
}
testcheck('/home/coloeus/Downloads/WebStom-2018.2.2.tar.gz');

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

Ответы [ 2 ]

0 голосов
/ 07 октября 2018

замените второй forEach на for..of, вот так:

chunks.forEach(async (chunk)=>{
    let skills = [];
    for (const uri of chunk) skills.push(await Datamanager.loadSkill(uri));
    DBManager.insertMany(skills,'skills');
})
0 голосов
/ 07 октября 2018

Проблема в том, что вы вызываете метод функции без построения класса, измените это:

async function testcheck(file) {
    try {
        let hash = await FileUtil.getSha1Sum(file);
        console.log(hash);
    }
    catch (e) {
        console.log(e);
    }
}

на следующее:

async function testcheck(file) {
    try {
        const fileUtil = new FileUtil();
        let hash = await fileUtil.getSha1Sum(file);
        console.log(hash);
    }
    catch (e) {
        console.log(e);
    }
}

И проверьте, если другой console.log()внутри обещанного вызова функции в течение getSha1Sum(...) выполняется.

...