JavaScript 中使用 Generator的方法(2)
正如你所看到的,我们可以轻松改变每批处理项目的个数,不去考虑执行器,回到正常的同步执行方式 —— 所有这些都不会影响我们的 renderItems 方法。
取消
我们来考虑下传统的功能 —— 取消。在我promises cancellation in general ( 译文:如何取消你的 Promise? ) 这篇文章中已经详细谈到了。所以我会使用其中一些代码:
function runWithCancel(fn, ...args) { const gen = fn(...args); let cancelled, cancel; const promise = new Promise((resolve, promiseReject) => { // define cancel function to return it from our fn // 定义 cancel 方法,并返回它 cancel = () => { cancelled = true; reject({ reason: 'cancelled' }); }; onFulfilled(); function onFulfilled(res) { if (!cancelled) { let result; try { result = gen.next(res); } catch (e) { return reject(e); } next(result); return null; } } function onRejected(err) { var result; try { result = gen.throw(err); } catch (e) { return reject(e); } next(result); } function next({ done, value }) { if (done) { return resolve(value); } // 假设我们总是接收 Promise,所以不需要检查类型 return value.then(onFulfilled, onRejected); } }); return { promise, cancel }; }
这里最好的部分是我们可以取消所有还没来得及执行的请求(也可以给我们的执行器传递类似AbortController 的对象参数,所以它甚至可以取消当前的请求!),而且我们没有修改过自己业务逻辑中的一行的代码。
暂停/恢复
另一个特殊的需求可能是暂停/恢复功能。你为什么想要这个功能?想象一下,我们渲染了 1000 行数据,而且速度非常慢,我们希望给用户提供暂停/恢复渲染的功能,这样他们就可以停止所有的后台工作读取已经下载的内容了。让我们开始吧!
// 实现渲染的方法还是一样的 function* renderItems() { for (item of items) { yield renderItem(item); } } function runWithPause(genFn, ...args) { let pausePromiseResolve = null; let pausePromise; const gen = genFn(...args); const promise = new Promise((resolve, reject) => { onFulfilledWithPromise(); function onFulfilledWithPromise(res) { if (pausePromise) { pausePromise.then(() => onFulfilled(res)); } else { onFulfilled(res); } } function onFulfilled(res) { let result; try { result = gen.next(res); } catch (e) { return reject(e); } next(result); return null; } function onRejected(err) { var result; try { result = gen.throw(err); } catch (e) { return reject(e); } next(result); } function next({ done, value }) { if (done) { return resolve(value); } // 假设我们总是接收 Promise,所以不需要检查类型 return value.then(onFulfilledWithPromise, onRejected); } }); return { pause: () => { pausePromise = new Promise(resolve => { pausePromiseResolve = resolve; }); }, resume: () => { pausePromiseResolve(); pausePromise = null; }, promise }; }
内容版权声明:除非注明,否则皆为本站原创文章。