<script> // 定义三个异步操作 let task1 = () => { return new Promise((resolve, reject) => { // 1秒之后打印字符串 setTimeout(() => { console.log('task1 执行完毕') resolve('task1'); }, 1000) }) } let task2 = () => { return new Promise((resolve, reject) => { // 2秒之后打印字符串 setTimeout(() => { console.log('task2 执行完毕') // resolve('task2'); reject('task2') }, 2000) }) } let task3 = () => { return new Promise((resolve, reject) => { // 3秒之后打印字符串 setTimeout(() => { console.log('task3 执行完毕') resolve('task3'); }, 3000) }) } // 让三个异步操作,一个接一个的执行, // 第一个任务处理结果传递给第二个任务, // 第二个任务处理的结果传递给第三个任务 function *main(result) { // 执行第一个任务 result = yield task1(result); console.log(11, result); // 执行第二个任务 result = yield task2(result); console.log(22, result); // 执行第三个任务 result = yield task3(result); console.log(33, result); // 返回最终的结果 return result; } // 启动程序 let m = main('red'); // 执行第一个任务 // 第一次传递不需要接收参数 m.next().value.then(() => { // 执行第二个任务 m.next('green').value.then(() => { // 执行第三个任务 m.next('yellow').value.then((res) => { console.log('最终的结果', res); }, () => { m.next('blue').value.then((res) => { console.log('最终的结果', res); }) }) }) })
可以看出,通过next()方法遍历通过then()方法监听,需要一层一层嵌套,于是ES6提供了co模块,又提供了co方法,用于简化状态函数的启动
代码如下
// 通过co方法启动main co(main) // 直接监听最终的结果 .then(res => console.log('最终结果是:', res), err => console.log('执行失败了', err))
实现co方法:
function co(gen) { // 返回一个promise方法 return new Promise((resolve, reject) => { // 执行generator函数 let g = gen(); // 定义递归函数 function myNext(res) { // 定义运行结果 let result; // 为了防止代码出现错误 我们可以将语句放入try catch中 try { result = g.next(res); } catch(e) { // 出现错误程序中断 return reject(e); } // 一旦遍历完成,终止执行 if(result.done) { return resolve(result.value); } // 进入下一项 result.value.then(() => { myNext(result.value); }) .catch(err => console.log(err)) } // 执行next myNext(); }) }