91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

redux-saga原理是什么

發布時間:2020-12-08 14:00:51 來源:億速云 閱讀:153 作者:小新 欄目:web開發

這篇文章將為大家詳細講解有關redux-saga原理是什么,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

Generator函數的自動流程控制

在redux-saga中,saga是指一些長時操作,用generator函數表示。generator函數的強大之處在于其可以手動的暫停、恢復執行,且可以與函數體外進行數據交互,看如下例子:

function *gen() {
  const a = yield 'hello';
  console.log(a);
}
cont g = gen();
g.next(); // { value: 'hello', done: false }
setTimeout(() => g.next('hi'), 1000)  // 此時 a => 'hi'   一秒后打印‘hi'

可以看出來genrator函數何時進行下一步操作完全取決于外部的調度時機,且其內部執行狀態也由外部的輸入決定,這使得generator函數可以很方便的做異步流程控制。舉個例子,我們首先讀取一個文件的內容作為查詢參數,然后請求一個查詢接口并把返回的內容打印出來:

function getParams(file) {
  return new Promise(resolve => {
    fs.readFile(file, (err, data) => {
      resolve(data)
    })
  })
}
function getContent(params) {
  //  request返回promise
  return request(params)
}
function *gen() {
  const params = yield getParams('config.json');
  const content = yield getContent(params);
  console.log(content);
}

我們可以手動控制gen函數的執行:

const g = gen();
g.next().value.then(params => {
  g.next(params).value.then(content => {
    g.next(content);
  })
})

以上可以達到我們的目的,但是過于繁瑣,我們想要的是generator函數可以自動的執行,可以寫一個簡易的自動執行函數如下:

function genRun(gen) {
  const g = gen();
  next();
  function next(err, pre) {
    let temp;
    (err === null) && (temp = g.next(pre));
    (err !== null) && (temp = g.throw(pre));

    if(!temp.done) {
      nextWithYieldType(temp.value, next);
    }
  }
}
function nextWithYieldType(value, next) {
  if(isPromise(value)) {
    value
      .then(success => next(null, success))
      .catch(error => next(error))
  } 
}
genRun(gen);

此時generator函數便可以自動執行,事實上我們可以發現,generator的內部狀態完全是由nextWithYieldType決定的,我們可以根據yield的類型執行不同的處理邏輯。

Effect

事實上sagaMiddleware.run(saga)可以類似看做genRun(saga),而saga是由一個個的effect組成的,那么effect是什么?redux-saga官網的解釋:一個 effect 就是一個 Plain Object JavaScript 對象,包含一些將被 saga middleware 執行的指令。redux-saga提供了很多Effect創建器,如call、put、take等,已call為例:

function saga*() {
  const result = yield call(genPromise);
  console.log(result);
}

call(genPromise)生成的就是一個effect,它可能類似如下:

{
  isEffect: true,
  type: 'CALL',
  fn: genPromise
}

事實上effect只表明了意圖,而實際的行為由類似于上文的nextWithYieldType完成,例如:

function nextWithYieldType(value, next) {
  ...
  if(isCallEffect(value)) {
    value.fn(). then(success => next(null, success)).catch(error => next(error))  
  } 
}

當genPromise函數返回的promise被resolve后便會打印出結果。

生產者與消費者

觀察下面的例子

function *saga() {
  yield take('TEST');
  console.log('test...');
}

sagaMiddleware.run(test);

saga會在take('TEST')處阻塞,只有執行了dispatch({type: 'TEST'})后saga才能繼續運行(注意:此時的dispatch方法是經過sagaMiddleware包裝過的)。這給我們的感覺似乎很像是take是一個生產者,在等待disaptch的消費,事實上take只是一個Effect生成器,具體的處理邏輯依然是在nextWithYieldType完成的,類似于:

function nextWithYieldType(value, next) {
  ...
  // take('TEST')生成的effect簡單的認為是  {isEffect: true, type: 'TAKE', name: 'TEST'}
  if(isTakeEffect(value)) {
    channel.take({pattern: value.name, cb: params => next(null, params)})  
  } 
}

channel是一個任務生成器,它有兩個方法:take生成任務,put消費任務:

function channel() {
  /*
    task = {
      pattern,
      cb
    }
  */
  let _task = null;

  function take(task) {
    _task = task;
  }

  function put(pattern, args) {
    if(!_task) return;
    if(pattern == _task.pattern) _task.cb.call(null, args);
  }

  return {
    take,
    put
  }
}

顯然任務是在執行dispatch的時候被消費掉的,這個工作是在sagaMiddleware中做的,類似于如下:

const sagaMiddleware = store => {
  return next => action => {
    next(action);
    
    const { type, ...payload } = action;
    channel.put(type, payload);
  }
}

關于redux-saga原理是什么就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

东丰县| 吴旗县| 芦溪县| 黄陵县| 大洼县| 吉木乃县| 宝鸡市| 茂名市| 武汉市| 和顺县| 芷江| 祁阳县| 肇州县| 大姚县| 扶余县| 兰坪| 阳西县| 琼中| 广平县| 晋江市| 乡城县| 紫阳县| 读书| 江都市| 江门市| 嘉鱼县| 郧西县| 通许县| 凌源市| 丹东市| 黄大仙区| 昌平区| 金平| 武胜县| 定南县| 句容市| 孟村| 桐柏县| 前郭尔| 桂阳县| 呼图壁县|