代码之家  ›  专栏  ›  技术社区  ›  AlexZeDim

Refractroing:从mongoose回调返回或将值推送到新的数组值

  •  1
  • AlexZeDim  · 技术社区  · 7 年前

    职务 我的问题是“正确的”,如果你 如果你有任何想法,你可以留下评论,我会重新命名它。

    我的代码逻辑:

    function main() {
        server.find({locale: "en_GB"}).exec(function (err, server) {
            for (let i = 0; i < server.length; i++) { //for example 20 servers
                rp({url: server[i].slug}).then(response => {
                    auctions.count({
                        server: server[i].name,
                        lastModified: {$gte: response.data.files[0].lastModified}
                    }).then(function (docs) {
                        if (docs < 0) {
                          //We don't insert data if they are already up-to-date
                        }
                        else {
                            //I needed response.data.files[0].url and server[i].name from prev. block
                            //And here is my problem
                            requests & insertMany and then => loop main()
                            })
                        }
                    })
                }).catch(function (error) {
                    console.log(error);
                })
            }
        })
    }
    
    main()
    

    else 像这样阻止:

    setTimeout(function () {
        //request every server with interval, instead of all at once
    }, 1000 * (i + 1));
    

    但我给自己制造了另一个问题,因为我需要递归我的 main() 就在那之后。所以我不能用: if (i === server[i].length-1) 调用垃圾收集器或重新启动 主() count 验证

    我改变了 for (let i = 0; i < server.length; i++) 从第三行到 .map 把它从第三条线移到 其他的 阻止但是 setTimeout 不适用于 .地图 版本,但正如你可能已经了解脚本失去正确的顺序,我不能拖延它。

    let array_new = [], array_new.push = response.data.files[0].url 使用 async/await . 但我不是这方面的专家,所以我已经浪费了几个小时了。所以现在唯一的问题是,我不知道怎么做 return 值来自 else block

    其他的

    function main() {
    --added let array_new = [];
    
    [v1]array_new.url += response.data.files[0].url;
    [v2]array_new.push(response.data.files[0].url);
    return array_new
    

    然后打电话 array_new .then ,但目前还没有一个是好的。所以也许有人会给我一个提示,或者让我看看已经回答的问题@Stackoverflow,这对我的情况可能有用。

    2 回复  |  直到 7 年前
        1
  •  1
  •   chridam Gino Claudi    7 年前

    由于您基本上是在处理承诺,因此可以重构函数逻辑以使用async await,如下所示:

    function async main() {
        try {
            const servers = await server.find({locale: "en_GB"}).exec()
            const data = servers.map(async ({ name, slug }) => {
                const response = await rp({ url: slug })
                const { lastModified, url } = response.data.files[0]
                const count = await auctions.count({
                    server: name,
                    lastModified: { $gte: lastModified }
                })
    
                let result = {}
                if (count > 0) result = { name, url }
    
                return result
            }).filter(d => Object.keys(d).length > 0)
    
            Model.insertMany(data)
        } catch (err) {
            console.error(err)
        }   
    }
    
        2
  •  1
  •   caffeinated.tech    7 年前

    你的问题在于你的承诺模糊了逻辑。你的 main 函数递归地调用自己N次,其中N是服务器的数量。这将通过节点进程和处理所有请求的MongoDB以指数级的速度累积内存。

    与其跳转到async/await,不如先使用promises并等待N个查询的批处理完成,然后再开始另一个批处理。你可以用[承诺.全部]来做这个。

    function main() {
      server.find({locale: "en_GB"}).exec(function (err, server) {
        // need to keep track of each promise for each server
        let promises = []
    
        for (let i = 0; i < server.length; i++) {
          let promise = rp({
            url: server[i].slug
          }).then(function(response) {
            // instead of nesting promises, return the promise so it is handled by 
            //  the next then in the chain.
            return auctions.count({
              server: server[i].name,
              lastModified: {
                $gte: response.data.files[0].lastModified
              }
            });
          }).then(function (docs) {
            if (docs > 0) {
              // do whatever you need to here regarding making requests and 
              //  inserting into DB, but don't call main() here.
              return requestAndInsert();
            }
          }).catch(function (error) {
              console.log(error);
          })
          // add the above promise to out list.
          promises.push(promise)
        }
        // register a new promise to run once all of the above promises generated
        //  by the loop have been completed
        Promise.all(promises).then(function () {
          // now you can call main again, optionally in a setTimeout so it waits a 
          //  few seconds before fetchin more data.
          setTimeout(main, 5000);
        })
      })
    }
    
    main()