如何停止类/函数继续执行Node.js中的代码 [英] How to stop class/functions from continuing to execute code in Node.js

查看:192
本文介绍了如何停止类/函数继续执行Node.js中的代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经对此提出了一些问题,但是也许这个问题会带来更好的答案(我对问题的回答不好)

I have made a few questions about this already, but maybe this question would result in better answers(i'm bad at questions)

我有一堂课,称为FOO,在这里我称为异步启动函数,该函数启动创建FOO类的过程。这个FOO类执行许多不同的计算,以及使用node.js requets模块发布/获取计算。

I have one class, called FOO, where I call an async Start function, that starts the process that the class FOO was made to do. This FOO class does a lot of different calculations, as well as posting/getting the calculations using the node.js "requets" module.

-我正在使用电子UI (通过按按钮执行功能等)来创建和启动FOO类-

-I'm using electron UI's (by pressing buttons, that executes a function etc..) to create and Start the FOO class-

class FOO {
  async Start(){
    console.log("Start")
    await this.GetCalculations();
    await this.PostResults()
  }
  
  async PostResults(){
    //REQUESTS STUFF

    const response = {statusCode: 200} //Request including this.Cal
    console.log(response)
    //Send with IPC
    
    //ipc.send("status", response.statusCode)
  }
  
  async GetCalculations(){
    for(var i = 0; i < 10; i++){
      await this.GetCalculation()
    }

    console.log(this.Cal)
  }

  async GetCalculation(){
    //REQUEST STUFF
    const response = {body: "This is a calculation"} //Since request module cant be used in here.

    if(!this.Cal) this.Cal = [];

    this.Cal.push(response)
  }
}
        
var F1 = new FOO();
        
F1.Start();

现在想象一下这段代码,但是带有A还有更多步骤和更多要求。在其中,完成FOO类中的所有任务可能需要几秒钟/分钟。

Now imagine this code but with A LOT more steps and more requests ect. where it might take seconds/minutes to finish all tasks in the class FOO.

-Electron有一个停止按钮,当用户希望计算停止时,用户可以按下该按钮。

-Electron got a stop button that the user can hit when he wants the calculations to stop-

我将如何阻止整个课程继续下去?

How would I go about stopping the entire class from continuing?

在某些情况下,用户可能会随后停止并重新启动,因此我一直在尝试找出一种方法来阻止代码完全运行,但是用户仍然可以创建一个新类并开始该类,而无需在后台运行其他类。

In some cases, the user might stop and start right after, so I have been trying to figure out a way to STOP the code from running entirely, but where the user would still be able to create a new class and start that, without the other class running in the background.

我一直在考虑 tiny-worker模块,但是创建工人时,需要1-2秒,这降低了快速计算程序的目的。

I have been thinking about "tiny-worker" module, but on the creation of the worker, it takes 1-2 seconds, and this decreases the purpose of a fast calculation program.

希望这个问题比其他问题要好。

Hopefully, this question is better than the other ones.

更新:

应用我得出的不同答案背后的逻辑:

Applying the logic behind the different answers I came up with this:

await Promise.race([this.cancelDeferred, new Promise( async (res, req) => {
        var options ={
            uri: "http://httpstat.us/200?sleep=5000"
        }

        const response = await request(options);

        console.log(response.statusCode)

    })])

但是即使

this.cancelDeferred.reject(new Error("User Stop"));

被调用,请求 statuscode的响应在请求完成时仍会打印出来。

Is called, the response from the request "statuscode" still gets printed out when the request is finished.

我得到的answares显示了一些我不知道的好的逻辑,但是问题是它们都只停止了请求,而代码却使请求成为现实。响应仍将执行,并且在某些情况下会触发新请求。这意味着我必须向Stop函数发送垃圾邮件,直到它完全停止为止。

The answares I got, shows some good logic, that I didn't know about, but the problem is that they all only stop the request, the code hanlding the request response will still execute, and in some cases trigger a new request. This means that I have to spam the Stop function until it fully stops it.

推荐答案

将问题作为整个函数框架进行序列化异步操作的调用,并且您希望用户能够单击取消/停止按钮并导致异步操作链中止(例如,停止执行任何操作,并保全获得试图获得的最终结果)。

Framing the problem as a whole bunch of function calls that make serialized asynchronous operations and you want the user to be able to hit a Cancel/Stop button and cause the chain of asynchronous operations to abort (e.g. stop doing any more and bail on getting whatever eventual result it was trying to get).

我可以想到几种方案。

1。每个操作都会检查某些 state 属性。您使这些操作成为具有 aborted 的某些对象的一部分。国家财产。每个异步操作的代码在完成后都必须检查该state属性。可以连接取消/停止按钮来设置此状态变量。当前异步操作完成后,它将中止其余操作。如果您使用诺言来对您的操作进行排序(看起来像是这样),那么您可以拒绝当前的诺言,从而导致整个链中止。

1. Each operation checks some state property. You make these operations all part of some object that has a aborted state property. The code for every single asynchronous operation must check that state property after it completes. The Cancel/Stop button can be hooked up to set this state variable. When the current asynchronous operation finishes, it will abort the rest of the operation. If you are using promises for sequencing your operations (which it appears you are), then you can reject the current promise causing the whole chain to abort.

2 。创建一些异步包装器函数,该函数自动为您合并cancel 状态如果您所有实际的异步操作都属于一小部分操作(例如全部使用 request 模块),那么您可以围绕使用的任何请求操作创建包装函数,当任何操作完成时,它都会为您检查状态变量或将其合并到返回的promise中如果已停止,则它拒绝返回的诺言,从而使整个诺言链中止。这样做的好处是,您只需要在一个位置执行 if ,其余代码就可以切换为使用包装的请求函数版本而不是常规版本

2. Create some async wrapper function that incorporates the cancel state for you automatically. If all your actual asynchronous operations are of some small group of operations (such as all using the request module), then you can create a wrapper function around whichever request operations you use that when any operation completes, it checks the state variable for you or merges it into the returned promise and if it has been stopped, it rejects the returned promise which causes the whole promise chain to abort. This has the advantage that you only have to do the if checks in one place and the rest of your code just switches to using your wrapped version of the request function instead of the regular one.

3。将所有异步步骤/逻辑放入可以杀死的另一个进程中。(在我看来)就像使用大锤解决一个小问题,但是您可以启动child_process(也可以是node.js)程序)执行多步异步操作,并且当用户按下停止/取消键时,您只是杀死了子进程。您正在监视child_process并等待结果的代码将获得最终结果或已停止的指示。您可能要在这里使用实际的进程而不是工作线程,以便获得完全的中止状态,以便正确回收该进程使用的所有内存和其他资源。

3. Put all the async steps/logic into another process that you can kill. This seems (to me) like using a sledge hammer for a small problem, but you could launch a child_process (which can also be a node.js program) to do your multi-step async operations and when the user presses stop/cancel, then you just kill the child process. Your code that is monitoring the child_process and waiting for a result will either get a final result or an indication that it was stopped. You probably want to use an actual process here rather than worker threads so you get a full and complete abort and so all memory and other resources used by that process gets properly reclaimed.

请注意,这些解决方案均不使用任何无限循环或轮询循环。

Please note that none of these solutions use any sort of infinite loop or polling loop.

例如,假设您的实际异步操作使用的是 request()模块。

For example, suppose your actual asynchronous operation was using the request() module.

您可以定义一个高范围承诺,如果用户单击取消/停止按钮:

You could define a high scoped promise that gets rejected if the user clicks the cancel/stop button:

function Deferred() {
    let p = this.promise = new Promise((resolve, reject) => {
        this.resolve = resolve;
        this.reject = reject;
    });
    this.then = this.promise.then.bind(p);
    this.catch = this.promise.catch.bind(p);
    this.finally = this.promise.finally.bind(p);
}    

// higher scoped variable that persists
let cancelDeferred = new Deferred();

// function that gets called when stop button is hit
function stop() {
   // reject the current deferred which will cause 
   //    existing operations to cancel
   cancelDeferred.reject(new Error("User Stop"));

   // put a new deferred in place for future operations
   cancelDeferred = new Deferred();
}

const rp = require('request-promise');

// wrapper around request-promise
function rpWrap(options) {
     return Promise.race([cancelDeferred, rp(options)]);
}

然后,您只需调用 rpWrap()随处可见,而不是调用 rp(),如果按下停止按钮,它将自动拒绝。然后,您需要对异步逻辑进行编码,以使如果有任何拒绝,它都会中止(通常是promises anywa的默认和自动行为)。

Then, you just call rpWrap() everywhere instead of calling rp() and it will automatically reject if the stop button is hit. You need to then code your asynchronous logic so that if any reject, it will abort (which is generally the default and automatic behavior for promises anywa).

这篇关于如何停止类/函数继续执行Node.js中的代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆