循环内的 Promise

2023-12-25

在下面的代码中,我有一个无限循环,我不知道为什么会发生。我最好的猜测是因为里面的函数是async循环不会等待它,因此循环永远不会停止。解决这个问题的最佳方法是什么?

 var generateToken = function(userId) {
    return new Promise(function(resolve, reject) {
        User.findOne({userId: userId}, function(err, user) {
            if (user !== null) {
                var loop = true;
                while (loop) {
                    var token = Common.randomGenerator(20);
                    (function(e) {
                        User.find({tokens: e}, function(err, result) {
                            if (err) {
                                loop = false;
                                reject('Error querying the database');
                            } else {
                                if (result.length === 0) {
                                    if (user.tokens === undefined) {
                                        user.tokens = [];
                                    }
                                    user.tokens.push(e);
                                    loop = false;
                                    resolve();
                                }
                            }
                        });
                    })(token);
                }
            } else {
                return reject('UserNotFound');
            }
        });
    });
};

该函数接收一个 userId (User.findOne()用于查找用户,如果没有具有该 id 的用户,则拒绝承诺)并创建一个unique该用户的随机令牌(randomGenerator) ,将其添加到保存在 MongoDB 中的用户实体并将其返回给调用者。

(NOTE有一些反对票说这个问题与this one https://stackoverflow.com/questions/7268579/for-loop-and-async-callback-in-node-js这并不是因为我的代码中已经有一个闭包,但它仍然不起作用。这个问题更多的是关于如何将循环变量绑定到闭包)


你是对的,你不能像你试图做的那样循环。

JavaScript 是单线程的。只要主线程在你的循环中while(loop)声明,没有其他东西有机会运行。如果你的主线程本身正在改变,这一切都可以loop变量,但这并不是正在发生的事情。相反,你正在尝试改变loop异步响应中的变量,但由于您的主线程正在循环,因此永远无法处理异步响应,因此您的loop变量永远不会改变,因此是一个非生产性的无限循环。

要修复此问题,您必须更改为不同的循环结构。常见的设计模式是创建一个本地函数,其中包含要重复的代码。然后,运行异步操作,如果在异步结果处理程序中,您决定要重复该操作,则只需从其中再次调用本地函数即可。因为结果是异步的,所以堆栈已展开,这在技术上不是堆栈构建的递归。它只是启动该功能的另一个迭代。

我对代码中的逻辑有点困惑(其中有零个注释来解释它),所以我不完全确定我是否正确,但总体思路如下:

var generateToken = function(userId) {
    return new Promise(function(resolve, reject) {
        User.findOne({userId: userId}, function(err, user) {
            function find() {
                var token = Common.randomGenerator(20);
                User.find({tokens: e}, function(err, result) {
                    if (err) {
                        reject('Error querying the database');
                    } else {
                        if (result.length === 0) {
                            if (user.tokens === undefined) {
                                user.tokens = [];
                            }
                            user.tokens.push(e);
                            resolve();
                        } else {
                            // do another find until we don't find a token
                            find();
                        }
                    }
                });
            }

            if (user !== null) {
                find();
            } else {
                reject('UserNotFound');
            }
        });
    });
};

我应该注意到你的错误处理不完整User.findOne()手术。

仅供参考,不断查询直到得到的整个逻辑result.length === 0只是看起来很奇怪。这个逻辑看起来很奇怪,而且闻起来像“在紧密循环中轮询数据库”,这通常是一件性能非常差的事情。我怀疑,如果我们在更高层次上理解整个问题,就会有更有效的方法来解决这个问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

循环内的 Promise 的相关文章

  • 使用 Javascript 实现 Tinder 风格的拖放手势?

    我正在尝试找出哪些库可以用于仅使用 Javascript 的 Tinder 风格拖放手势 需要创建一个响应拖动手势的 HTML 元素 触摸并按住时 允许元素跟随用户的手指移动 当用户移开手指时 该元素会 动画回到原来的位置 如果元素在释放时
  • 整个页面都是玻璃板

    有没有一种简单的方法可以在整个 HTML 页面上拥有一个 玻璃窗格 而不管缩放 幻灯片事件 平台 浏览器 移动 桌面 我所说的 简单 是指纯 CSS 支持 而不是插件 后备 插件建议也可能有用 Thanks 如果您只是指所有内容之上的一层
  • Nodejs 在路由器页面中包含 socket.io

    我有一个 Express Node 应用程序 并且我试图通过不在 app js 中包含所有 socket io 内容来保持代码整洁 我不知道解决这个问题的最佳方法 这是我最初的想法 感觉不是最干净的 app js var express r
  • 如何更改点击事件上的引导插入符指向方向

    我正在使用 2 3 2 引导程序 因为当我单击菜单按钮时 我可以更改插入符号图标的位置 我需要当我单击图标插入符号向上时 当您单击另一个项目时 插入符号返回到初始状态 这怎么可能 导航代码 div div class container d
  • 如何获得相对于特定父级的偏移量?

    我想获取元素相对于的偏移量特定的父母不是直接的 也不是文档 我在互联网上查找并找到了offset http api jquery com offset and position http api jquery com position jQ
  • 将其作为参数传递给 addEventListener()

    我想添加change一组复选框的事件 我如何访问this在我的事件函数中 这样当我执行事件时我可以访问复选框的值 这是我当前的代码 var checkboxes document getElementsByClassName cb Arra
  • 尝试使用 CasperJS 跟踪 iframe 中的链接

    我正在尝试使用CasperJS http casperjs org index html跟踪 iframe 中的链接 但我似乎无法获取 iframe 的文档 这是使用我找到的 iframe 示例页面进行的测试 第三个 iframe 有一个名
  • 按日期对 JSON 进行排序

    我知道这一定相对简单 但我有一个 JSON 数据集 我想按日期排序 到目前为止 我每次都会遇到问题 现在我将日期存储为this lastUpdated 如果有帮助的话 我可以访问 jquery 但我意识到 sort 是本机 JS 提前致谢
  • 无法提取 Typescript 中的对象值

    我一直在尝试将 JavaScript Web 表单转换为 Typescript 但无法弄清楚如何处理以下内容 在 JavaScript 中有效 let fieldValues JSON parse cookieData let keys O
  • jQuery 如何通过不同的列值计算表中的行数

    如何按表列计算不同的表行 Example table thead tr th NAME th th TECHNOLOGY th tr thead tbody tr td john td td jQuery td tr tr td mark
  • 如何使用javascript从特定标签获取HTML文档中的所有textNode?

    如何在不使用xpath或treewalker的情况下从单个数组中的一组特定标签中获取所有textNodes blockquote em h4 h6 p IE不允许您使用xpath和treewalker 请帮助我 如果脚本仅适用于 IE 那就
  • 'DOMException:使用'option:selected'选择器时无法在'Element'上执行'querySelectorAll'

    我正在运行一个页面 该页面在以下行中引发错误 var label select find option selected html select find option first html 为了完整起见 这里是完整的 jQuery 函数
  • 如何将输入字段值作为 URL 查询字符串传递,单击提交按钮将打开该字符串?

    我必须输入这样的字段
  • 如何与使用 child_process.spawn 创建的新创建的服务器交互

    我正在尝试为我的私人托管的 反恐精英全球攻势 服务器制作一个前端 当我点击运行服务器时 在前端 一切正常 服务器启动并记录到控制台 但是如何查看服务器IP地址 服务器中的玩家等信息呢 这是我到目前为止运行服务器的内容 router post
  • 如何在 NodeJs 中发送 Google 索引批量请求的多部分/混合请求?

    我正在使用 Nodejs 进行连接谷歌API v35 0 0 https www npmjs com package googleapis告诉 Google 更新或从 Google 索引中删除页面 当我通过发送请求时 我陷入了多部分 混合请
  • jQuery 单击附加元素不起作用

    我有一个数组 我正在从 Array 获取数据并在 jQuery Append to list 中使用它 但是当我单击列表项时 它只显示最后一个元素 var array 1 2 7 3 4 8 5 6 9 for var i 0 i lt a
  • 正则表达式获取两个方括号之间的数字

    您好 我需要使用正则表达式在 JavaScript 中获取两对方括号内的字符串 这是我的字符串 12 23 asd 到目前为止我尝试的是使用这种模式 d 我需要获得价值12使用正则表达式 您可以使用以下正则表达式 d 这将提取12 from
  • 限制线的长度

    我正在尝试画一条代表 弹弓 的线 并且希望它具有最大拉伸长度 在 p5 中 我在位置和位置之间画了一条线 line posA x posA y posB x posB y posA 是鼠标 x 和 y posB 是画布上圆的位置 我想要做的
  • 在 Map() 的条目上使用 Promise.all

    我正在使用 Map 来表示一些键 值对 let myMap new Map myMap set foo bar myMap set foo2 bar42 对于每个 Map 条目 我执行一个返回 Promise 的函数 所有这些 Promis
  • Chrome 中的 addEventListener

    我正在关注 Lynda com 上有关新 DOM 事件模型的教程 这是我正在使用的代码 function addEventHandler oNode sEvt fFunc bCapture if typeof window event un

随机推荐