javascript - 保存 JavaScript Promise 以备将来使用

标签 javascript node.js promise

我正在使用 Node.js 构建服务器端 RESTApi。当我自己测试时,Node 工作正常。但是当它真的在那里时,它仍然可能面临溢出问题。当有很多请求时,比如有超过 5 个 child_process (spawn) 同时工作,每个进程花费更长的时间,基本上减慢一切。

我的想法是检查当前进程是否低于某个限制(比如,一次限制为 3 个进程),如果超过限制,我将请求保存到一个数组中,每当当前进程低于限制,我使用 .shift() 弹出数组中最旧的一个并处理它。

然而,当涉及到 Promise 时,它​​变得困难,因为我不知道我们是否可以将 Promise 存储到数组中,或者我是否应该让进程暂停几秒钟,我认为这不是好主意。

如果你想保持 promise 并在未来将 promise 返回给客户,通常的做法是什么?

对不起,如果我没有说清楚。下面总结一下我的疑惑: 1. 我们可以保存一个 promise 以备将来使用吗? 2.我们是否将它们保存在数组中? 3. 我是否应该使用其他方法来保持 promise ,例如使用 sleep() 或只是一个 while 循环来等待此过程继续进行?

谢谢!

最佳答案

say there are more than 5 child_process (spawn) working at the same time, each process is taking longer time, basically slow down everything.

在现实世界的部署中——你不会以这种方式处理带有子任务的 CPU 密集型任务——你会使用一个健全的并发数据结构(比如 mqtt 或数据库上的队列)并将工作分配给你部署的工作人员然后将其发送回服务器。

原因是服务器总是会宕机——而你要防止部分工作。

My idea is to check if the current process is below a certain limit (like, limit to 3 processes at a time), if it exceed the limit, I save the requests into an array, and whenever the current processes is below the limit, I use .shift() to pop the oldest one in the array and process it.

这是执行此操作的代码,我请求您阅读第一点并且不要在生产中使用该代码,而是在您的部署中限制它(例如,如果您使用 AWS 将规模限制为 3 个实例):

// lifted from my bluebird-api project
function throttle(fn, concurrency = 20, Promise) {
    // create an array of workers as resolved promises
    const workers = Array(concurrency).fill(Promise.resolve());
    const work = []; // pending work
    return function (...args) {
        // when there is work, pull the next worker
        const worker = workers.pop();
        if (worker === undefined) { // if there is no pending worker
            let resolve, reject;
            // store the promise for the result
            const promise = new Promise((res, rej) => {
                resolve = res; 
                reject = rej;
            });
            // and add it to the queue
            work.unshift({ args, resolve, reject, promise });
            return promise;
        }
        // after the worker is ready, call the function
        worker = worker.then(() => (fn(...args), null));
        worker.then(function pump() {
            if (work.length) { // after you're ready
                const {resolve, reject, args} = work.pop();
                // continue draining the queue
                worker = worker.then(() => fn(...args)).then(resolve, reject).then(pump);
            } else { // or declare ready
                workers.push(worker);
            }
            return null;
        });
        return worker;
    }
} 

代码摘自bluebird-api这仍然是 WIP。

What is the normal way if you want to hold a promise and return the promise to client in future?

是的,它完全是一个受支持的案例 - 它不会泄漏内存并且是安全的(在现代 promise 实现中)。虽然再次 - 这是一个 XY 问题 - 你不应该在 Node 服务器上以这种方式分配工作。

当您实现正确的解决方案(排队和卸载到不同的服务)时,您可以创建一个 promise 队列,您可以在其中返回一个 promise 并稍后在队列准备就绪时解决它。

关于javascript - 保存 JavaScript Promise 以备将来使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45037180/

相关文章:

mysql - NodeJS 应用程序 (Express) 中的 Google Cloud SQL 连接 --> 错误 : connect ENOENT

javascript - pouchdb 向 fancytree promise

javascript - 如何 promise ?

javascript - 如何使用 CSS 或 JavaScript 将图像用于复选框?

node.js - 不使用框架的纯 Node.js 文件上传(多部分 POST)

javascript - 从元素列表中找出哪个元素被点击

node.js - 转发到另一个路由处理程序而不在 Express 中重定向

javascript - 如何将 $promise 返回的数据分配给全局变量

javascript - Realm + React Native 最佳实践用户设置与同步

javascript - Three.js 如何确定我的场景是否已加载