Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

请问一下 effects 中 yield put() 是一个非阻塞过程,如何做到 effects 中阻塞调用另一个 effect. #1212

Closed
pingsoli opened this issue Sep 12, 2017 · 12 comments

Comments

@pingsoli
Copy link

Code to reproduce the issue: (请提供可复现的代码或者步骤)

Expected behavior: (预期的正常效果)

Actual behavior: (实际效果)

Versions of packages used: (哪个库的哪个版本出现的问题)

@nihgwu
Copy link
Member

nihgwu commented Sep 12, 2017

dva@2 已经提供了相应的例子,sorrycc/blog#48

yield put({ type: 'addDelay', payload: { amount: 2 } });
yield take('addDelay/@@end');
const count = yield select(state => state.count);
yield put({ type: 'addDelay', payload: { amount: count, delay: 0 } });

@hopperhuang
Copy link
Contributor

redux-saga/redux-saga#744
你可以看一下这里的解决方案。
直接用call 去阻塞调用你的那个effect。

但是在dva里面有一个问题,就是你要怎么获取你到你想调用的那个effect方法,因为dva里面的effect方法是写在model里面的,你自己想想看有没有什么方法从model里面获取目标方法,然后用call去调用吧。

@hopperhuang
Copy link
Contributor

hopperhuang commented Sep 12, 2017

@nihgwu

effect 前后会额外触发 /@@start 和 /@@end 的 action,

请问这段代码是saga里面封装的吗??我在dva的源码里面看不到有哟。可以告诉我这段源码的地址吗?

@nihgwu
Copy link
Member

nihgwu commented Sep 12, 2017

@hopperhuang 在 dva-core 里面

@pingsoli
Copy link
Author

@hopperhuang dva 中的 effect 是写在 model 中的,我正是为这事儿烦,不知道如何取出来。看了 @nihgwu 的方法,我觉得是正解,先调用,然后立即 take 阻塞接收。

@hopperhuang
Copy link
Contributor

hopperhuang commented Sep 12, 2017 via email

@sorrycc sorrycc closed this as completed Sep 15, 2017
@xiabingwu
Copy link

为什么要阻塞put,请问这里的应用场景是什么

@WavinFlag
Copy link

为什么要阻塞put,请问这里的应用场景是什么

如果 put 的 action 是被 saga (在 dva 中是 effect) 处理的,那么 yield put 返回时,对应的 saga/effect 还没有完成执行(redux-saga 的 scheduler 会将其入队,稍后再逐步调度),这样就不满足某些状态流程的阻塞要求。

如果我没有记错的话,put action 被 reducer 处理则没有这个问题,因为 yield put 返回时,对应的 reducer 已经执行完成了。

@WavinFlag
Copy link

这些其实都是 redux-saga 的注意事项,只不过在 dva 中 effects 的写法,generator function 都是作为 effect、通过 put action 触发的。实际上会有很多 generator function 并不直接处理 action,而是被其他 saga/generator function 调用。

我个人的做法是,还原到直接使用 redux-saga 时的写法,只有直接响应 action 的 generator function 才放到 dva effects 中,其他一律游离出来。

const model = {
  // ...

  effects: {
    * showItem({ payload }, { call }) {
  
      // 用:
      yield call(showItemFirstStageProcedure)
      yield call(showItemSecondStageProcedure)

      // 而不是:
      // yield put({ type: 'showItemFirstStage' })
      // yield take('showItemFirstStage/@@end')
      // yield put({ type: 'showItemSecondStage' })
      // yield take('showItemSecondStage/@@end')
      // ...after second stage
    },

    // ...
    // end effects
  },

  // ...
  // end model
}

游离的 generator function 中需要 saga 的 call/select/... 时,可以直接从 saga 中 import:

import { effects } from 'dva/saga'

const { call, select } = effects

但是 dva 为其 effects 中的方法提供的 puttake 经过一次封装(即 namespace 前缀处理),必须通过 effects methods 传递:
in https://github.com/dvajs/dva/blob/master/packages/dva-core/src/getSaga.js#L141

return { ...sagaEffects, put, take };

或者就写完整的 action type:

import { effects } from 'dva/saga'

const { take } = effects

// then
take(`${namespace}/${actionType}`)

@2534290808
Copy link

put.resolve()是阻塞的

yield put.resolve({ type: 'addDelay', payload: { amount: 2 } });
const count = yield select(state => state.count);
yield put({ type: 'addDelay', payload: { amount: count, delay: 0 } });

put.resolve()就是阻塞的,详情见redux-saga API

@miaozilong
Copy link

为什么要阻塞put,请问这里的应用场景是什么

如果 put 的 action 是被 saga (在 dva 中是 effect) 处理的,那么 yield put 返回时,对应的 saga/effect 还没有完成执行(redux-saga 的 scheduler 会将其入队,稍后再逐步调度),这样就不满足某些状态流程的阻塞要求。

如果我没有记错的话,put action 被 reducer 处理则没有这个问题,因为 yield put 返回时,对应的 reducer 已经执行完成了。

是的,我已经试过了yield put(reducers)是同步的 而yield put(effects)是异步的

@miaozilong
Copy link

为什么不能直接put ,非要yield put???

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants