【问题标题】:Is there a way to run asynchronously typescript class methods without blocking the main thread?有没有办法在不阻塞主线程的情况下异步运行打字稿类方法?
【发布时间】:2019-08-01 18:40:30
【问题描述】:

我正在制作一个应用程序,它可以从我的 Outlook 邮件中的某些消息中获取附件。我有一个 Mongodb 来存储来自这些附件的信息。问题是接收这些附件的过程非常耗时,这就是为什么我想让它在主线程之外的另一个线程中工作,以防万一我想要以某种方式取消它或跟踪它的进度。

现在我知道 nodejs 的主要问题是它是单线程的。但尽管如此,我还是找到了几个模块,比如 Bull、Webworker-threads 或 workerpool,它们可能会帮助我解决这个问题,当然我也尝试过使用 Node 的 ChildProcess。这些模块的主要问题是它们既可以从文件运行异步代码,也可以使用不依赖于当前数据的静态函数(据我从示例和文档中了解到的)。但在我的情况下,我不能以这种方式使用。

问题是 - 有没有办法让我在不改变我的整个代码架构的情况下异步运行类方法?

//sync.running.controller.ts
import { ConfigServiceFuncs } from "../config.service";
import { SyncRunningService } from "./sync.running.service";

export class SyncRunningController {
  constructor(private readonly configService : ConfigServiceFuncs, private     readonly syncService : SyncRunningService) {}

  //Method that runs when a Put request is made

  @Put
    //I want to have it working in another thread so that I could send another requests, like Delete or Get

  async StartUpdate() {
    this.syncService.startSync();
  }
}



//sync.running.service.ts

import {GetMessagesFromMail } from "./code.js";
@Injectable()
export class SyncRunningService {

  constructor(@Inject('SOME_MODEL') private readonly syncModel :  Model<SomeModel>, private readonly configService : ConfigServiceFuncs){}


  async syncFunc(){

    this.syncDatabase();

  }
  
  async SyncDatabase(){

    databaseObjects = await GetMessagesFromMail();
    /*
     Then goes the code for adding info to database 
    */

}

    }
  
}

【问题讨论】:

  • 假设您有代价高昂的循环,您可以定义一个函数来生成“yielding”承诺:const y = () =&gt; new Promise(r=&gt;setTimeout(r, 0)) 并在 async 函数中执行您的工作,偶尔调用 await y(),以返回到你的程序的其余部分。事情仍然是“块状”,但您不会以这种方式冻结所有内容。
  • 你能解释一下这个生成器到底在做什么吗?我不太擅长 Promises。
  • 更新了代码,使其工作原理更加清晰。
  • 据我了解,逻辑是这样的:当我的 Put 请求发出时,我运行一个函数 StartUpdate()。在那里,我可以使用带有 yield 的生成器在 SyncRunningService 中执行我的函数 syncFunc() 的一些代码,然后返回 StartUpdate,然后返回 syncFunc() 从我离开的行中执行该函数的另一部分。但问题是我仍然必须等到 StartUpdate() 函数完成,以便我可以使用其他请求来取消我的更新,例如删除请求来取消我的更新。

标签: javascript node.js mongodb typescript outlook


【解决方案1】:

我想出了解决这个问题的方法。感谢 mongoose https://mongoosejs.com/ 我能够通过它的功能与 mongoDB 进行通信。 因此,我能够创建一个独立的 .ts 文件,创建类来访问 Controller 和 Service 的方法。

接下来我使用了 Nodejs 的 Child_Process fork(),这样我就有了一个可用的异步功能。

我认为这个解决方案的主要问题是重复代码,这样我们每次在其余代码中更新模式时都需要更新模式。

//sync.ts - standalone file
//imports
var mongoose = require('mongoose');
mongoose.connect('mongodb://path/to/database', {useNewUrlParser : true});
var db = mongoose.connection;

db.once('open',function(){
  //functions to create models
  function CreateModel1(){
    var schema = new mongoose.Schema({
    //declare your schema here
    });
    var model = mongoose.model('Model1',schema);
    return model;
  }
  /*
  same function for Model2
  */

  var model1 = CreateModel1();
  var model2 = CreateModel2();

  //declare class instances for your service class, if any
  var syncServiceClass = new SyncRunningService(/* ... */);
  (async function(){
    syncServiceClass.syncFunc();
  })();
}

//.controller.ts
/*
  ...
*/
async StartUpdate(){
   const child_process = require('child_process');

   var worker_process = child_process.fork(__dirname + "/sync.ts");

   worker_process.on('close',function(){
     console.log("child process was finished");
     return;
  }
}

【讨论】:

  • 基本上你已经重新发明了 BullJS (github.com/OptimalBits/bull),但使用的是 MongoDB 而不是 Redis。车辆将完成这项工作(在某种程度上),我建议您切换到功能齐全的队列管理器,如 BullJS(或 RabbitMQ、Kafka 或其他数百万队列提供程序之一)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-05
  • 2016-07-04
  • 2021-10-15
  • 2012-05-07
  • 1970-01-01
相关资源
最近更新 更多