我必须按顺序运行一系列异步任务,每个任务之间有一段延迟,直到达到某个任务为止。我试着用es6发生器做这个。这是代码
function delay(callback, timeout) {
return new Promise((resolve, reject) => setTimeout(() => {
try {
resolve(callback());
} catch(e) {
reject(e);
}
}, timeout));
}
function run(generatorFunc) {
function continuer(verb, arg) {
var result;
try {
result = generator[verb](arg);
} catch (err) {
return Promise.reject(err);
}
if (result.done) {
return Promise.resolve(result.value);
} else {
return Promise.resolve(result.value).then(onFulfilled, onRejected);
}
}
var generator = generatorFunc();
var onFulfilled = continuer.bind(continuer, "next");
var onRejected = continuer.bind(continuer, "throw");
return onFulfilled();
}
run(function* () {
var json;
while (true) {
json = yield delay(() => fetch('http://api.com/get.json').then(res => res.json()), 1000)
if (json.isCompleted) {
return json;
}
}
}).then(json => console.log(json));
现在,如果用户按下按钮,我想“破坏”该承诺链,如何在不引入全局变量的情况下做到这一点?感谢
答案 0 :(得分:0)
{
const run = task => {
const taskState = task();
let reject = null;
const process = new Promise((rs, rj) => {
(function next (dat) {
const {value, done} = taskState.next(dat);
(done) ? rs(value) : value.then(next).catch(reason => rj(reason));
}());
reject = rj;
});
//
// Expose *hook* like what @Felix Kling suggested
//
process.kill = sig => {
taskState.return(); // close generator
reject(sig); // reject promise
};
return process;
}
// To test interrupt, we create a task involving a async task which is 'idle' forever
function* task () {
// imagine big memory has been already allocated here
// and one async task ... does not response ...
yield new Promise(() => {}); /*pending forever*/
}
// setup process, we'll see 'KILL' or 'TIMEOUT' on console.error channel
let process = run(task);
process.catch(e => console.error('stderr', e)).then(/*never*/);
// interrupt cases
document.body.addEventListener('click', e => process.kill('KILL'));
setTimeout(() => process.kill('TIMEOUT'), 10e3);
}