V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
ethusdt
0.01D
V2EX  ›  程序员

redux-saga 中 channel 的原理是怎样的?

  •  
  •   ethusdt ·
    FaiChou · Dec 14, 2021 · 1242 views
    This topic created in 1605 days ago, the information mentioned may be changed or developed.

    摊牌了, 源码没看懂. 有个地方想请教, 例子:

    function* watchAndDo() {
      const channel = yield actionChannel('TEST');
      while (true) {
        const payload = yield take(channel);
        yield call(Api, payload);
      }
    }
    

    这个例子中, 假如一起来了 10 个 TEST, 则会一个一个执行. 那么这里 channel 是如何做到等待循环里的 block 结束再派发下一个动作的?

    目前了解到: 创建 channel 后, dispatch 的消息会加入到 buffer 中, buffer 是一个数组.

    ethusdt
        1
    ethusdt  
    OP
       Dec 14, 2021
    明白了:
    ethusdt
        2
    ethusdt  
    OP
       Dec 14, 2021
    function take(cb) {
    if (closed && buffer.isEmpty()) {
    cb(END)
    } else if (!buffer.isEmpty()) {
    cb(buffer.take())
    } else {
    takers.push(cb)
    cb.cancel = () => remove(takers, cb)
    }
    }

    上面是 channel.js 里的代码, 首先 dispatch() 或者 put() 会将消息放到 buffer 中, 当 buffer 为空, 则还没有任何消息到来, 这时候 take(channel) 或者 take('MESSAGE') 会存到 takers 中, 在下次消息到的时候, 取出来一个来执行:

    function put(input) {
    if (closed) {
    return
    }
    if (!takers.length) {
    return buffer.put(input)
    }
    const cb = takers[0]
    takers.splice(0, 1)
    cb(input)
    }

    如果阻塞时候 buffer 来了很多消息, 后来阻塞结束(比如例子中 while 的新一轮循环), 判断 `!buffer.isEmpty()` 会直接从 buffer 中取出一条消息来执行 cb(buffer.take())
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3484 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 11:44 · PVG 19:44 · LAX 04:44 · JFK 07:44
    ♥ Do have faith in what you're doing.