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
};
}
内容版权声明:除非注明,否则皆为本站原创文章。
