Javascript Nodejs,通过回调关闭mongo db连接

Javascript Nodejs,通过回调关闭mongo db连接,javascript,node.js,mongodb,asynchronous,callback,Javascript,Node.js,Mongodb,Asynchronous,Callback,我有回调、异步思维等问题 执行程序: 连接到mongoDb 创建url-+从locArray添加部件 发送get请求(针对每个请求) 将数据保存到mongo db 密切联系 问题: 如果连接在jsonDataFromApi中的最后一行关闭——“服务器实例池被破坏”,然后每个请求的所有数据都保存到数据库中 因此,callback(db)被发送到另一个地方-closeMongoDb 但出现了错误 无法读取未定义的属性“close” 我认为,问题在于异步、发送回调等 const Mong

我有回调、异步思维等问题

执行程序:

  • 连接到mongoDb
  • 创建url-+从locArray添加部件
  • 发送get请求(针对每个请求)
  • 将数据保存到mongo db
  • 密切联系
  • 问题:

    • 如果连接在jsonDataFromApi中的最后一行关闭——“服务器实例池被破坏”,然后每个请求的所有数据都保存到数据库中

    • 因此,
      callback(db)
      被发送到另一个地方-
      closeMongoDb

    • 但出现了错误 无法读取未定义的属性“close”

    我认为,问题在于异步、发送回调等

        const MongoClient = require('mongodb').MongoClient;
            const Array = require('node-array');
            const request = require('request');
    
            var locationArray = [
              'location1',
              'location2',
              'location3',
              'location4'
            ];
    
            var dataFromLocApi = (loc, callback) => {
              request({
                url: `https://example.com/${loc}`,
                json: true
              }, (error, response, body) => {
                if (error){
                callback('Error connection to url.');
                } else{
                callback(undefined, body.result);
              }
             });
            };
    
            var jsonDataFromApi = (urldb, callback) => {
            MongoClient.connect(urldb, (err, db) => {
              if (err) {
                console.log('MongoDb connection error.');
              }
              console.log('MongoDb - connected.');
              locationArray.forEachAsync(function(loc, index, arr) {
                dataFromLocApi(loc, (errorMessage, results) => {
                  if (errorMessage) {
                    console.log(errorMessage);
                  } else {
                    console.log(JSON.stringify(results, undefined, 2));
                    db.collection('testCollection').insert(results, function(error, record) {
                      if (error)
                        throw error;
                      console.log("data saved");
                    });
                  }
                });
    
              }, function() {
                console.log('complete');
              });
            callback(db);
            });
            }
    
    var closeMongoDb = (urldb, callback) => {
        jsonDataFromApi(urldb, (error, db) => {
          if (error){
            callback('Close connection - failure');
          } else{
            db.close();
            console.log('MongoDb connections was closed.');
        }
        });
        }
    
        closeMongoDb('mongodb://127.0.0.1:27017/testDb', (err, db) => {
    
          console.log('DONE');
        } );
    

    这里肯定存在异步问题。 在调用
    db.close()
    之前,您没有等待处理项目

    此外,您定义的函数的语义也不清楚。例如,函数
    closeMongoDb
    基本上应该关闭数据库,就是这样。但这里还有另一项工作:获取数据,然后关闭数据库

    另外,我可能会使用
    async
    模块,而不是
    节点数组
    ,因为最后一个模块似乎可以解决其他问题

    我已经重构了代码。请阅读我的评论。我尽量把它说清楚

    const MongoClient=require(“mongodb”).MongoClient;
    常量请求=要求(“请求”);
    //我们将使用异步模块
    //这是处理异步行为的经典模块。
    const async=require(“异步”);
    //如您所见,此函数接受回调
    //如果连接到数据库时出错
    //它通过回调将其传递给调用方(err)
    //这是一种普遍模式
    const connectToDb=函数(urldb,回调){
    MongoClient.connect(urldb,(err,db)=>{
    如果(错误){
    log(“MongoDb连接错误”);
    回调(err);
    回来
    }
    //如果一切正常,将db作为数据传递给调用方。
    回调(未定义,db);
    });
    };
    //此方法获取单个位置的数据。
    //带有错误/数据的逻辑是完全相同的。
    const getData=(loc,callback)=>{
    请求(
    {
    网址:`https://example.com/${loc}`,
    json:true
    },
    (错误、响应、正文)=>{
    如果(错误){
    回调(“错误连接到url”);
    回来
    }
    回调(未定义,body.result);
    }
    );
    };
    //此函数遍历每个位置,提取数据并将其保存到数据库
    //最后一个参数是回调,我将其命名为allDataFetchedCb以明确说明这一点
    //我们在处理完所有位置后才调用它
    //所有内容都保存到数据库中。
    const saveDataFromLocations=函数(位置、数据库、allDataFetchedCb){
    //这里的第一个参数是一个项目数组
    //第二个是我们希望为每个项执行的异步函数
    //当处理单个项目时,我们调用回调。我将其命名为“locProcessedCB”
    //所以很清楚会发生什么。
    //第三个参数是一个回调,当所有项
    //已经处理过了。
    async.each(
    位置,
    功能(loc、locProcessedCb){
    获取数据(loc,(apiErr,结果)=>{
    if(apiErr){
    控制台日志(apiErr);
    //我们无法处理该项,请将错误传递给我们。
    locProcessedCb(apiErr);
    回来
    }
    console.log(
    `已从api获取数据:${JSON.stringify(
    后果
    未定义,
    2.
    )}`
    );
    db.collection(“testCollection”).insert(结果、函数(dbError){
    if(dbError){
    //还有一个错误,我们无法处理该项目。
    locProcessedCb(dbError);
    回来
    }
    //确定调用此函数后,项目处理无错误
    //所以我们告诉async.each函数:好的,很好,继续处理下一个函数。
    locProcessedCb();
    });
    });
    },
    功能(err){
    //我们会在所有物品处理完毕或发生任何错误后到达这里。
    如果(错误){
    allDataFetchedCb(错误);
    回来
    }
    log(“所有位置都已处理”);
    //好的,把db对象传上去。
    allDataFetchedCb(未定义,db);
    }
    );
    };
    //此函数是一个入口点。
    //它逐个调用上述所有函数。
    const getDataAndCloseDb=函数(urldb、位置、回调){
    //好吧,让我们连线。
    connectToDb(urldb,(err,db)=>{
    如果(错误){
    回调(err);
    回来
    }
    //现在让我们把所有的东西都准备好。
    saveDataFromLocations(位置,数据库,(错误,数据库)=>{
    如果(错误){
    回调(err);
    回来
    }
    //如果没有db对象,或者没有close方法,我们想知道。
    如果(!db | |!db.close){
    回调(新错误(“无法关闭数据库连接”);
    }
    //关闭数据库。
    db.close(错误=>{
    //如果没有错误,err==未定义或null
    //所以这个调用等于回调(未定义);
    回调(err);
    });
    });
    });
    };
    const locationArray=[“location1”、“location2”、“location3”、“location4”];
    //最后调用函数,将所有需要的数据传递到内部。
    获取数据