Redux-Saga入门

Generator 函数扫盲

a、形式上,Generator 函数是一个普通函数,但是有两个特征:
1、function关键字与函数名之间有一个星号;
2、函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
b、generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行
c、返回值是遍历器对象。每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。
d、yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
e、注意yield的返回值A和其后表达式的返回值B不是一个意思,B是赋给value的

function* f() {
  for(var i = 0; true; i++) {
    var reset = yield i;    // 每次next时执行该行,下面一行等下一个next才执行
    if(reset) { i = -1; }
  }
}

var g = f();

g.next() // { value: 0, done: false }
g.next() // { value: 1, done: false }
g.next(true) // { value: 0, done: false }

f、yield*表达式,用来在一个 Generator 函数A里面执行另一个 Generator 函数B,这里“执行”的意思不是执行B(),即返回值不是遍历器对象C,而是返回C的for...of结果,就好似将B的yield代码拷贝到了A里:

function* foo() {
  yield 'a';
  yield 'b';
}

function* bar() {
  yield 'x';
  yield* foo();
  yield 'y';
}

// 等同于
function* bar() {
  yield 'x';
  yield 'a';
  yield 'b';
  yield 'y';
}

// 等同于
function* bar() {
  yield 'x';
  for (let v of foo()) {
    yield v;
  }
  yield 'y';
}

for (let v of bar()){
  console.log(v);
}
// "x"
// "a"
// "b"
// "y"

g、异步任务的封装

var fetch = require('node-fetch');

function* gen(){
  var url = 'https://api.github.com/users/github';
  var result = yield fetch(url);
  console.log(result.bio);
}

//  调用
var g = gen();
var result = g.next();

result.value.then(function(data){
  return data.json();
}).then(function(data){
  g.next(data);
});

Saga 用法

1、redux-saga 是一个用于管理 Redux 应用异步操作的中间件(又称异步 action)。
2、redux-saga 通过创建 Sagas 将所有的异步操作逻辑收集在一个地方集中处理,可以用来代替 redux-thunk 中间件。
3、Sagas 监听发起的action,然后决定基于这个 action来做什么:是发起一个异步调用(比如一个 fetch 请求),还是发起其他的action到Store,甚至是调用其他的 Sagas
4、一个实例

// 1、写reducer
import { handleActions } from 'redux-actions'
import { LOGIN_SUCCEEDED, LOGIN_FAILED, LOGOUT_SUCCEEDED, LOGOUT_FAILED} from '../constants/login'
// 语法:handleActions({actionCreator},initialState)
export default handleActions(
    {
        [LOGIN_SUCCEEDED](state, action) {
            return { ...state, ...action.accountInfo,hasLogin: true }
        },
        [LOGIN_FAILED](state, action) {
            alert(action.message)
            return state
        },
    },
    {
        hasLogin: false,
    },
)
// 2、写saga
function* login(action) {
    try {
        //  语法:call([context, fn], ...args)
        const data = yield call(                         
            getJSON,
            URLS.LOGIN,
            { password: action.password, accountName: action.accountName },
        )
        yield put({ type: LOGIN_SUCCEEDED, accountInfo: data })       // 成功时改变state状态
        yield hashHistory.push('/project')
    } catch (e) {
        yield put({ type: LOGIN_FAILED, message: e })
    }
}

function* loginSaga() {
    yield* takeEvery(LOGIN_REQUESTED, login)   // 这一步监听LOGIN_REQUESTED事件
}

export {
    loginSaga,
}
// 3、调用方
import { LOGIN_REQUESTED } from '../../constants/login'

class Login extends React.Component {
    componentDidMount() {
    }
    login = e => {
        const { dispatch } = this.props
        e.preventDefault()
        e.stopPropagation()
        dispatch({                                                        // 这一步触发LOGIN_REQUESTED事件                                
            type: LOGIN_REQUESTED,
            password: this.refs.password.value,
            accountName: this.refs.accountName.value,
        })
    }
    render() {

    }
}

你可能感兴趣的:(Redux-Saga入门)