【问题标题】:insertMany inside setTimeout and for loop with async functions在 setTimeout 和带有异步函数的 for 循环中的 insertMany
【发布时间】:2019-03-16 12:21:54
【问题描述】:

我正在尝试编写以下代码并使其同步工作,但唯一的问题是它可以与console.log 一起正常工作,它会在 1 秒内延迟打印数组中的每个项目,但不能与以下结构:

for (let i = 0; i < array.length; i++) {
    setTimeout(function () {
        1.http request via rp or request.get (I receive a huge data array)
        2. .map results 
        3.insert to Mongo via mongoose 
     }
}

目前我有以下代码:

request.get({url: array[i].url}), function (error, body) {
    body.map(element => {
        //do stuff, it works fine
     });
     collection.insertMany(body, function (err, docs) {
         //#justloggerthings
     }

或者我有几乎与rp 相同的版本而不是request.get 默认情况下我有mongoose.Promise = global.Promise;

为什么这会导致问题?因为body.length 是一个非常庞大的数据集,会占用大量内存。 (现在想象一下insertMany 的 20 多个数组)

所以 Mongo 试图立即 insertMany 来自请求的所有响应(当它们准备好时,没有 1000 秒的延迟)。实际上这就是为什么我选择 request 而不是 rp (request-promise) 但它看起来也很异步。所以我应该从npm 中选择另一个http get 模块并切换到它。而且不用担心吗?

或者我应该把这个操作包装成promise ||当我正确完成时,每次(例如 1000 秒)创建一个异步函数并在循环内调用它。在这种情况下,我在 StackOverflow 上发现的唯一实际情况是:

How to insert data to mongo synchronously (Nodejs, Express)

有点过时了。那么有什么想法吗?

【问题讨论】:

  • 如果您不想一次插入所有响应,则不要使用 insertMany。循环响应并一一插入。
  • 实际上我不确定.create 50'000+ 个元素是否比使用.insertMany(array) 更好。我来自request 的回复不是一个简单的文档,而是包含大量文档的庞大数组。 [TL:DR:我需要一个接一个地插入 10+ 个这个数组 (body),而不是一次全部插入。这就是为什么我使用for 和setTimeout 逻辑在这种情况下很简单:通过url 数据集body 请求(它是一个数组),然后将其插入Mongo,因为如果我一次插入所有它们,它需要一个大量内存(就像我之前提到的)]
  • 如果要按顺序执行,请在循环中使用await,而不是map

标签: javascript node.js mongodb asynchronous mongoose


【解决方案1】:

解决我的问题的实际代码是:

async function test (name, url, lastModified) {
    try {
        const response = await rp({uri: url, json: true});
        response.map(async (element) => {
            if (element.buyout > 0) {
                element.price = (element.buyout / element.quantity);
            }
            element.lastModified = lastModified
        });
        return collection.insertMany(response);
    } catch (err) {
        console.error(err)
    }
}

async function addAsync() {
    const z = await test();
    console.log(z);
}

addAsync();

【讨论】:

    【解决方案2】:

    好吧,我没有你的实际代码,所以我会用伪代码写你能做什么。

    const chunkArray = (array, chunkSize) => {
        let i,j,chunks = [];
        for (i = 0, j = array.length; i < j; i += chunkSize) {
            chunks.push(array.slice(i, i + chunkSize));
        }
        return chunks;
    }
    
    for (let i = 0; i < array.length; i++) {
        let bigArray = await request('your data url');
        // do some mapping or whatever
        // then break your large array into smaller chunks
        let chunks = chunkArray(bigArray, 10);
        let j;
        for (j = 0; j < chunks.length; j++) {
            await collection.insertMany(chunks[j]);
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-09
      • 1970-01-01
      • 2019-04-07
      • 1970-01-01
      • 2019-07-17
      • 1970-01-01
      • 1970-01-01
      • 2018-09-24
      相关资源
      最近更新 更多