【问题标题】:get data asynchron from Rest api and loading them to mongodb with node.js - using promises从 Rest api 获取数据异步并使用 node.js 将它们加载到 mongodb - 使用 Promise
【发布时间】:2019-03-12 12:34:42
【问题描述】:

我使用 Javascript 的次数不多,现在很挣扎。

简而言之:

我想从 Rest-API 检索数据并将它们批量插入到正在运行的 MongoDB 数据库的集合中。

我目前的知识:

由于 Javascript 是一种单线程语言。因此,如果您希望在其他事情完成后完成某些事情(主要是异步操作),您必须使用回调。 回调: 回调是一个函数 A,它作为参数传递给函数,并且必须在该函数的最后执行以保证 A

  • 作为最新动作执行

  • 必须异步检索的数据/对象可能可用,因此它们可以在 A 中使用

承诺:

是 Javascript 中引入的一个相对较新的特性,可以用来处理 Javascript 的单线程特性吗? Promise 有不同的状态(已完成、已拒绝、待处理、已结算)。

异步/等待: 这也是一项新功能,让异步函数的工作看起来更加同步,并防止过多的嵌套导致混乱。

我的场景:

这是一个具有使用“请求”来执行 REST-Request 的函数的类。

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);
            });
        });
    }
 ...
}

在以下函数中,我读取了要从 JSON 文件中检索的数据的 URI。加载和解析的数组被拆分为 100 个条目大小的数组,因为我想稍后一次批量插入 100 个对象。在内部 forEach 循环中,我尝试使用带有 await 的 Promise 来加载技能,因此必须使用 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')
            })
        }
    });
}

起初,我遇到了关于 MongoDB 的错误。但我意识到错误是由于尝试插入空数组引起的。 所以,老实说,我在另一个问题上遇到了类似的问题。

我尝试执行 Linux shell 命令(sha1sum [file])来获取校验和。文件很大,我

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)});
    };
 ...
}

以下代码仅在控制台打印“未定义”。上面的代码打印出想要的结果。

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');

所以我的问题是:我的代码有什么问题。 我希望你能给我一个提示。我已经阅读了很多关于使用 Promise 的内容,但不知道为什么它不起作用。

【问题讨论】:

标签: javascript promise es6-promise


【解决方案1】:

将第二个 forEach 替换为 for..of,如下所示:

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

【讨论】:

    【解决方案2】:

    问题是你在没有构建类的情况下调用函数的方法,改变这个:

    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);
        }
    }
    

    并检查getSha1Sum(...) 中您承诺的函数调用中的另一个console.log() 是否被执行。

    【讨论】:

    • 函数被声明为静态的,所以不需要对象/实例来使用我认为的方法。但是我尝试通过删除 executeCommand() 的静态声明,getSha1Sum 并按照您的建议使用 new FileUtil() 创建了一个对象,但得到了相同的结果
    • @coloeus 你能添加一个console.log() 作为getSha1Sum(file) 的第一行吗,例如:`getSha1Sum(file){ console.log('got file'); ... } 检查函数是否被调用?
    • 是的,函数被调用了。
    猜你喜欢
    • 2020-05-08
    • 2018-03-11
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    • 1970-01-01
    • 1970-01-01
    • 2014-05-18
    相关资源
    最近更新 更多