JavaScript基础回顾(七):迭代

21 阅读3分钟

迭代内容不多,我想到的实例是 redux-saga,于是先去研究了一下 redux-saga。在研究 redux-saga 时,这个 redux 异步操作中间件是强大,但是实际用起来会非常不方便,远不如 redux-thunk,而且新的 reduxjs/toolkit 也默认使用 redux-thunk。我又想到了 dva,一个 redux-saga 的非常好的解决方案,虽然 dva 主体没在继续更新,但其核心依旧在 Umi 中发光发热。所以就先有了这一篇《在react项目中使用Umi:dva源码简析之redux-saga的封装》,然后回过头给这一篇画上了句号。

迭代器

  • 每个迭代器代表对可迭代对象的一次有序遍历。
  • 使用 next() 方法进行迭代,返回 { done, value },done 为 true 代表迭代完成,迭代完成后 value 只能返回 undefined。

生成器

  • 生成器的形式是一个函数:function* name(params) {} 或 * func() {},但箭头函数不能用来定义生成器函数。
  • 调用生成器函数会产生一个生成器对象,这个对象实现了 Iterator 接口,支持 next() 方法。
  • 生成器函数遇到 yield 后会停止执行,再调用 next() 方法恢复执行。
  • yield 必须直接位于生成器函数的定义中。
  • yield* [1, 2, 3] 等同于 for (const x of [1, 2, 3]) { yield x }。
  • 异步生成器是生成器的一个特殊形式,允许在生成器函数中使用 await 表达式,for await...of 用于异步迭代。
async function* asyncGenerateNumbers() {
  await new Promise(resolve => setTimeout(resolve, 1000));
  yield 1;
  await new Promise(resolve => setTimeout(resolve, 1000));
  yield 2;
  await new Promise(resolve => setTimeout(resolve, 1000));
  yield 3;
}

async function runAsyncGenerator() {
  for await (const number of asyncGenerateNumbers()) {
    console.log(number); // 依次输出:1 2 3
  }
}

runAsyncGenerator();

JavaScript 中的遍历

数组常用的方法

  • at:支持负索引,[] 不支持负索引。
  • concat:返回新数组,是对所有参数数组的浅拷贝
  • forEach:array.forEach(item => {})
  • map: array_new = array.map(item => item_new)
  • filter: array_filtered = array.filter(item => item_filtered)
  • reduce: value_new = array.reduce((accumulator, currentValue, currentIndex, array) => { value_temp }, initialValue)

object

  • for...in:键遍历
  • object.keys():键遍历
  • object.values():值遍历
  • object.entries():键值对遍历

redux-saga——一个生成器函数的实践

redux-saga 是 redux 的一个用于处理副作用的中间件,是基于生成器函数实现的。

核心概念

  • Saga:Saga(一连串事件) 是一个特殊函数,它使用生成器函数来控制副作用的执行流程。可以把它想象成一个独立于主应用程序的线程,负责处理所有的副作用。
  • Effects:Effects 是描述副作用的对象,Saga 通过 yield 关键字来产出 Effects。这些 Effects 被 Saga 捕获并执行。

常用 API

  • call:用于执行普通函数或异步函数,并暂停 Saga 直到 Promise 解决或函数返回。例如,yield call(func, arg1, arg2)。
  • put:用于派发(dispatch)action。例如,yield put({type: 'ACTION_TYPE', paylod: data})。
  • take:用于监听特定的 action,当 action 被 dispatch 时,会触发后续的代码。例如,yield take('ACTION_TYPE')。
  • fork:用于并行执行 Saga,它允许你启动一个 Saga 并在后台运行,不会阻塞其他 Saga 执行。例如,yield fork(otherFunc, arg1, arg2)。
  • cancel:用于取消 fork 或 spawn 创建的任务。例如,yield cancel(task)。

更细节的使用推荐阅读