【问题标题】:How to use async-lock in nodejs app to lock a /get resource function如何在 nodejs 应用程序中使用 async-lock 来锁定 /get 资源功能
【发布时间】:2021-07-04 20:35:14
【问题描述】:

我一直在尝试使用 async-lock npm 模块来锁定 /get 资源执行。

import cors from "cors";
import express from "express";
import AsyncLock from "async-lock";
import _ from "lodash";

const app = express();
const port = process.env.port || 3001;

app.use(cors());
app.use(express.json());

let synchonizationKey: string = "";
let lock = new AsyncLock();

app.get("/pckg", (req, res) => {
  let id = _.uniqueId();
  console.log("--------------Request ", id, " arrived");

  lock.acquire(
    synchonizationKey,
    function () {
      console.log("--------------Request ", id, " lockAquired");

      setTimeout(function () {
        console.log("--------------Request ", id, " Done");
      }, 3000);
    },
    function (err, ret) {
      console.log("--------------Request ", id, " lockReleased");
      res.send({ id: id });
    },
    {}
  );
});

app.listen(port, () => console.log("Running on port#" + port));

输出:我从浏览器发出的 4 个获取请求。

--------------Request  1  arrived
--------------Request  1  lockAquired
--------------Request  1  lockReleased
--------------Request  2  arrived
--------------Request  2  lockAquired
--------------Request  2  lockReleased
--------------Request  3  arrived
--------------Request  3  lockAquired
--------------Request  3  lockReleased
--------------Request  4  arrived
--------------Request  4  lockAquired
--------------Request  4  lockReleased
--------------Request  1  Done
--------------Request  2  Done
--------------Request  3  Done
--------------Request  4  Done

我期待得到与question 中回答的类似行的结果

看起来,一旦回调中的所有同步部分执行完毕,锁就会被释放。

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 应该有一个函数叫done,next等...你需要在你的setTimeout代码块中手动调用它,如果有错误,一般需要通过它在那个函数中像:next(error),在这种情况下,async-lock 解决了什么类型的问题?你让它变得复杂了,你现在不需要任何回调库......改用标准async/await
  • 客户端可以调用 /pckg 来运行一系列异步调用。这些异步调用需要在 /pckg get 请求中得到保护。
  • @Nur 在某些情况下您可能需要锁。例如,多个客户端读取和更新同一个文件,其中第二个客户端不得开始读取文件,而另一个客户端尚未完成更新。当然,每个人都可以使用async/await 自己编写这样的锁定,但没有必要让每个人都重新发明轮子。是的,现在可能首选基于承诺的方法——这也得到了库的支持。但是使用基于回调的方法仍然没有错...

标签: node.js asynchronous


【解决方案1】:

如果您查看async-lock 包的docs,您会注意到acquire 函数具有以下签名

acquire(
  key,
  executeFunction,
  callbackFunction,
  options);

executeFunction 本身有签名的地方

function(done) {...}

done是一个回调函数,用于在你的临界区工作完成后调用callbackFunction,并且可以释放锁。您省略了 done 参数,因此没有手动调用 callbackFunction。因此,一旦executeFunction 完成,就会调用它(因此释放锁)。而且由于你的执行函数中的setTimeout当然也是异步的,它不会延迟executionFunction。

所以正确的使用方法,如下

lock.acquire(
  synchonizationKey,
  function (done) {  // <----- new parameter for the function
    console.log("--------------Request ", id, " lockAquired");

    setTimeout(function () {
      console.log("--------------Request ", id, " Done");
      done();  // <---- call the callback, once the lock can be released 
    }, 3000);
  },
  function (err, ret) {
    console.log("--------------Request ", id, " lockReleased");
    res.send({ id: id });
  },
  {});

这导致以下输出

--------------Request  1  arrived
--------------Request  1  lockAquired
--------------Request  2  arrived
--------------Request  3  arrived
--------------Request  4  arrived
--------------Request  1  Done
--------------Request  1  lockReleased
--------------Request  2  lockAquired
--------------Request  2  Done
--------------Request  2  lockReleased
--------------Request  3  lockAquired
--------------Request  3  Done
--------------Request  3  lockReleased
--------------Request  4  lockAquired
--------------Request  4  Done
--------------Request  4  lockReleased

【讨论】:

  • 非常感谢您的详细解释。现在可以了。糟糕的是,我没有仔细阅读文档。
猜你喜欢
  • 2012-09-23
  • 2022-12-19
  • 1970-01-01
  • 2013-10-09
  • 1970-01-01
  • 1970-01-01
  • 2020-10-28
  • 1970-01-01
  • 2016-10-20
相关资源
最近更新 更多