首页 > 解决方案 > Node JS + Express - 异步请求

问题描述

我正在尝试使用 Node.js + Express 作为 Web 服务器来学习一些东西,并尝试使其异步。我创建了一个应用程序来测试排序算法的时间复杂度(大学作业灵感),但它并没有像我预期的那样异步工作。对 Express 服务器的任何其他 REST 调用都将被阻止,直到前一个排序代码完成运行。我还使用“express-namespace-routes”来拥有一些命名空间,因此它看起来像一个 API 调用。

这是我的课排序:

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;
}
}

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

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));
  });
});

这是我打电话给服务器:

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

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

标签: node.jsalgorithmsortingexpressasynchronous

解决方案


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

你不能让 node.js 中的普通 Javascript 异步运行。唯一异步运行的东西是具有某种异步本机代码实现的东西,例如文件 I/O 或网络。然后,对那些本机异步操作使用回调或承诺的代码会将控制权返回给事件循环(允许其他事情运行),然后在调用它们的回调时恢复。但是,这些都不允许您自己的 Javascript 在 node.js 中“在后台运行”或“在没有阻塞的情况下运行并使用单个 Javascript 线程”。

Node.js 将您的 Javascript 作为单线程运行。所以,如果你在做一些大的排序算法,那会一直运行那个单线程直到它完成。它对你完全没有帮助async。所做的只是改变函数的返回值。它不会影响该函数中同步代码的运行方式。

如果您真的想在单个 Javascript 线程之外运行您的代码,那么您有以下选择:

  1. 使用 child_process 模块创建第二个 node.js 进程来运行您的排序代码。
  2. 使用 cluster 模块对您的应用程序进行集群,这样您就有多个相同的进程来处理请求,并且当一个进程运行您的排序算法时,另一个进程可以处理其他请求。
  3. 编写在另一个线程中运行排序并异步返回结果的本机代码(可能通过事件队列中的回调事件)。
  4. 创建一组您使用您最喜欢的进程间通信形式与之通信的工作 node.js 进程,然后您可以创建工作队列,您可以在其中将项目传递给您的工作进程,并在主 node.js 应用程序之外处理 CPU 消耗任务。

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

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

我只是希望该功能在“后台”中运行,我的代码不会这样做吗?

您不能在单个 node.js 进程中“在后台运行 Javascript”。node.js 的架构不是这样工作的。您的代码没有这样做。看来您误解了async函数的作用。

如果没有,我该怎么办?

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


推荐阅读