socket.io和异步事件

时间:2019-04-04 09:37:44

标签: javascript asynchronous mongoose socket.io

我在快递服务器中使用socket.io和猫鼬。

我的套接字正在使用以下代码监听事件:

from datetimerange import DateTimeRange

def simplify_ranges(dtrs):
    if not dtrs:
        return []
    dtrs = sorted(dtrs, key=lambda dtr: dtr.start_datetime)
    simplified = []
    current = dtrs[0]
    for dtr in dtrs[1:]:
        if current.intersection(dtr).is_valid_timerange():
            current = current.encompass(dtr)
        else:
            simplified.append(current)
            current = dtr
    simplified.append(current)
    return simplified

dtrs = [
    DateTimeRange("2019-01-25T00:00:00+0000", "2019-01-30T00:00:00+0000"),
    DateTimeRange("2019-01-01T00:00:00+0000", "2019-01-10T00:00:00+0000"),
    DateTimeRange("2019-01-21T00:00:00+0000", "2019-01-22T00:00:00+0000"),
    DateTimeRange("2019-01-20T00:00:00+0000", "2019-01-21T00:00:00+0000"),
    DateTimeRange("2019-01-06T00:00:00+0000", "2019-01-15T00:00:00+0000"),
]

print(*simplify_ranges(dtrs), sep='\n')
# 2019-01-01T00:00:00+0000 - 2019-01-15T00:00:00+0000
# 2019-01-20T00:00:00+0000 - 2019-01-22T00:00:00+0000
# 2019-01-25T00:00:00+0000 - 2019-01-30T00:00:00+0000

socket.on('do something', async () => { try { await doA(); doX(); await doB(); doY(); await doC(); } catch (error) { console.log(error); } }); doAdoB是使用猫鼬在数据库上写的异步操作,但通常它们可以是任何返回诺言的方法。

我希望“执行某些操作”同步运行。 如果事件队列同时处理更多事件,则mongodb中存在一致性问题。

换句话说,如果服务器收到两个“执行某事”事件,则我希望仅在第一个事件已完全处理时(在doC之后)处理接收到的第二个事件。不幸的是,“做某事”回调是异步的。

如何处理?

2 个答案:

答案 0 :(得分:1)

可以通过将要运行的函数添加到数组中,然后逐个运行它们来实现队列。我在下面创建了一个示例。

let queue = [];
let running = false;

const delay = (t, v) => {
   return new Promise((resolve) => { 
       setTimeout(resolve.bind(null, "Returned value from Promise"), t)
   });
}

const onSocketEvent = async () => {
  console.log("Got event");
  if (!running) {
    console.log("Nothing in queue, fire right away");
    return doStuff();
  }
  // There's something in the queue, so add it to it
  console.log("Queuing item")
  queue.push(doStuff);
}

const doStuff = async () => {
  running = true;
  const promiseResult = await delay(2000);
  console.log(promiseResult);
  
  if (queue.length > 0) {
    console.log("There's more in the queue, run the next one now")
    queue.shift()();
  } else {
    console.log("Queue empty!")
    running = false;
  } 
}

onSocketEvent();
setTimeout(() => onSocketEvent(), 1000);
setTimeout(() => onSocketEvent(), 1500);
setTimeout(() => onSocketEvent(), 2000);
setTimeout(() => onSocketEvent(), 2500);

答案 1 :(得分:0)

我建议在每次等待之间添加一个延迟。这将防止死锁的发生并解决您的问题。对于这种情况,我建议使用Caolan's异步库。

任务延迟示例:

setTimeout(function() { your_function(); }, 5000); // 5 seconds

如果您的函数没有参数且没有显式接收器,则可以直接调用setTimeout(func, 5000)

有用的jQuery timers plugin