节点JS + Express-异步请求 [英] Node JS + Express - Asynchronous request

查看:89
本文介绍了节点JS + Express-异步请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将Node.js + Express用作网络服务器,以使其异步。我已经创建了一个应用来测试排序算法的时间复杂度(大学作业的灵感),但该应用并非按照我的预期异步运行。在之前的排序代码完成运行之前,对Express服务器的任何其他REST调用都将被阻止。我还使用'express-namespace-routes'来命名空间,因此看起来像一个API调用。



这是我的类Sort:

  class Sort {
静态异步binarySearch(array,inf,sup,key){
let half = inf + Math.floor((sup-inf)/ 2);

如果(inf == sup)返回inf;
else if(key> array [half])返回this.binarySearch(array,half + 1,sup,key);
else if(key< array [half])返回this.binarySearch(array,inf,half,key);
否则返回一半;
}

静态异步binaryInsertionSort(array){
let changes = 0;
const time = process.hrtime();
for(let j = 1; j< array.length; j ++){
let key = array [j];
让i = j-1;
let posicao =等待this.binarySearch(array,0,j,key);
而(i> = posicao){
array [i + 1] = array [i];
我-;
changes ++
}
array [posicao] =键;
}
}

静态异步createRandomArray(size){
let array =等待this.createSortedArray(size);
for(让s = size; s> 0; s--){
let index = Math.floor(Math.random()* s);

let temp = array [s-1];
array [s-1] = array [index];
array [index] = temp;
}
返回数组;
}
}

这是我的index.js文件的一部分,其中我正在创建名称空间:

  routes.prefix('/ sorted',sorted => {
排序.get('/ binaryInsertion /:size',async(req,res)=> {
Sort.createRandomArray(req.params.size)
.then(array => Sort.binaryInsertionSort(数组))
.then(数据=> res.json(数据))
.catch(err => res.send(err));
});
});

这是我在呼叫服务器:

  $。ajax(`$ {arrayType} / $ {sortingAlgorithm} / $ {arraySize}`).then(console.log); 

有什么想法吗?我可能做错了什么?一切对我来说都是不同步的。问题不仅在binaryInsertionSort中,所以我认为问题不在算法代码中,因为它阻止了我所有已经实现的算法的请求

解决方案

首先,所有代码都是同步和阻塞的。全部是本地Javascript。
您不会调用任何内置的异步操作。



您无法使node.js中的普通Javascript异步运行。唯一异步运行的是具有某种本机代码实现(例如文件I / O或网络)异步的事物。并且,对那些本机异步操作使用回调或promise的代码将把控制权返回到事件循环(允许其他事情运行),然后在调用其回调时恢复执行。但是,所有这些都不允许您自己的Javascript在node.js中在后台运行或在不阻止和使用单个Javascript线程的情况下运行。



Node。 js将Javascript作为单线程运行。因此,如果您要执行某种大型排序算法,那将使该单个线程无效直到完成。使函数 async 完全对您没有帮助。所有要做的就是更改函数的返回值。它不会影响该函数中的同步代码的运行方式。



如果您确实想在单个Javascript线程之外运行代码,则可以使用以下选项: / p>


  1. 使用child_process模块​​创建第二个node.js进程来运行排序代码。

  2. 使用集群模块对应用程序进行集群,以便您有多个相同的进程处理请求,并且一个进程在运行排序算法时,另一个进程可以处理其他请求。

  3. 编写运行您的排序的本机代码在另一个线程中,并异步返回结果(可能通过事件队列中的回调事件)。

  4. 创建一组工作程序node.js进程,您可以使用自己喜欢的形式与之通信进程间通信,然后您可以创建工作队列,将项目传递到工作进程,并在main.js应用程序外部处理CPU消耗任务。




为什么会阻止?我正在异步调用它。


您不是在异步调用它。 async 函数不会使任何异步操作。它所做的只是允许 await 里面,并强制该函数的返回值是一个承诺。该函数内的任何Javascript仍将使用单个node.js线程运行,并且在运行时仍会阻塞。如果您对返回诺言的函数执行等待,这将暂停函数的执行,直到诺言得以解决并允许其他事情运行,但前提是您拥有全部您的任何函数都是同步代码,那么所有内容都将同步运行( .then()处理程序有一个小小的例外,它使它们等到下一个周期事件循环),但它仍然不允许同步代码在后台运行或类似的操作。


我只是希望该函数在后台运行,我的代码不会这样做吗?


您不能运行Javascript在单个node.js进程中的后台。 node.js的体系结构无法正常工作。您的代码没有这样做。似乎您误解了 async 函数的作用。


如果没有,可能会发生什么我做?


请参阅上面的四个编号选项。


I'm trying to learn some stuff with Node.js + Express as a web server, trying to make it asynchronous. I've created an app to test time complexity of sorting algorithms (college homework inspiration), but it is not working asynchronously as I was intending. Any other REST call to the Express server is blocked until the former sorting code finishes running. I'm also using 'express-namespace-routes' to have some namespaces, so that it looks like an API call.

This is my class Sort:

class Sort {
   static async binarySearch(array, inf, sup, key) {
    let half = inf + Math.floor((sup - inf) / 2);

    if (inf == sup) return inf;
    else if (key > array[half]) return this.binarySearch(array, half + 1, sup, key);
    else if (key < array[half]) return this.binarySearch(array, inf, half, key);
    else return half;
}

static async binaryInsertionSort(array) {
    let changes = 0;
    const time = process.hrtime();
    for (let j = 1; j < array.length; j++) {
        let key = array[j];
        let i = j - 1;
        let posicao = await this.binarySearch(array, 0, j, key);
        while (i >= posicao) {
            array[i + 1] = array[i];
            i--;
            changes++
        }
        array[posicao] = key;
    }
}

static async createRandomArray(size) {
    let array = await this.createSortedArray(size);
    for (let s = size; s > 0; s--) {
        let index = Math.floor(Math.random() * s);

        let temp = array[s - 1];
        array[s - 1] = array[index];
        array[index] = temp;
    }
    return array;
}
}

This is part of my index.js file, where I'm creating the namespace:

routes.prefix('/sorted', sorted => {
    sorted.get('/binaryInsertion/:size', async (req, res) => {
    Sort.createRandomArray(req.params.size)
      .then(array => Sort.binaryInsertionSort(array))
      .then(data => res.json(data))
      .catch(err => res.send(err));
  });
});

And this is me calling the server:

$.ajax(`${arrayType}/${sortingAlgorithm}/${arraySize}`).then(console.log);

Any idea? What could I possibly be doing wrong? Everything looks assynchronous for me. The problem is not only in the binaryInsertionSort, so I think the problem is not in the algorithm code, as it block requests for all my already implemented algorithms

解决方案

First off, all your code is synchronous and blocking. It's all local Javascript. You don't call any built-in asynchronous operations.

You can't make normal Javascript in node.js run asynchronously. The only things that run asynchronously are things that have some sort of native code implementation that is asynchronous such as file I/O or networking. And, then code that uses callbacks or promises for those natively asynchronous operations will return control back to the event loop (allowing other things to run) and then will resume when their callback gets called. But, none of that allows your own Javascript to "run in the background" or "run without blocking and using the single Javascript thread" in node.js.

Node.js runs your Javascript as single threaded. So, if you're doing some big sorting algorithm, that's going to hob that single thread until it's done. It does not help you at all to make the function async. ALL that does is change the return value of the function. It doesn't affect how the synchronous code in that function runs.

If you really want to run your code outside the single Javascript thread, then you have these options:

  1. Use the child_process module to create a second node.js process to run your sorting code.
  2. Use the cluster module to cluster your app so you have multiple identical processes serving requests and while one is running your sorting algorith, another can be handling other requests.
  3. Write native code that runs your sort in another thread and communicates back the result asynchronously (likely via a callback event in the event queue).
  4. Create a set of worker node.js processes that you communicate with using your favorite form of interprocess communication and then you can create work queue where you pass items to your worker processes and you handle the CPU consuming tasks outside the main node.js app.

Why would it block? I'm calling it asynchronously.

You aren't calling it asynchronously. An async function does not make anything asynchronous. All it does is allow await inside and force the return value of the function to be a promise. Any Javascript inside that function still runs with the single node.js thread and still blocks while its running. If you do an await on a function that returns a promise, that will suspend execution of the function until the promise resolves and allow other things to run, but if all you have in any of your functions is synchronous code, then everything is just going to run synchronously (there's one tiny exception for .then() handlers which just makes them wait until the next cycle of the event loop), but it still doesn't allow synchronous code to run "in the background" or anything like that.

I just want that function to run in the "background", wouldn't my code be doing this?

You can't "run Javascript in the background" in a single node.js process. The architecture of node.js does not work that way. Your code is not doing that. It appears you misunderstand what an async function does.

If not, what could I do?

See the four numbered options above.

这篇关于节点JS + Express-异步请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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