一、回调函数
优点:简单、容易理解;
缺点:不利于维护,代码耦合高;
function getData (url, callBack) { // 模拟发送网络请求 setTimeout(() => { // 假设 res 就是返回的数据 var res = { url: url, data: Math.random() } // 执行回调,将数据作为参数传递 callBack(res); }, 1000) } getData('/page/1?param=123', (res1) => { console.log(res1); getData(`/page/2?param=${res1.data}`, (res2) => { console.log(res2); getData(`/page/3?param=${res2.data}`, (res3) => { console.log(res3); }) }) })
二、事件监听
优点:容易理解,可以绑定多个事件,每个事件可以指定多个回调函数。
缺点:采用事件驱动模式,取决于某个事件是否发生,流程不够清晰。
三、发布/订阅(观察者模式)
类似于事件监听,但是可以通过"消息中心"了解现在有多少发布者,多少订阅者。
四、promise对象
优点:可以利用then方法,进行链式写法;可以书写发生错误的回调函数;
缺点:一旦新建Promise,会立即执行,中途无法取消。如果没有设置回调函数,Promise内部抛出错误,外部无法知道。如果是pending进行中状态,不知道刚刚开始还是即将完成。
function getDataAsync (url) { return new Promise((resolve, reject) => { setTimeout(() => { var res = { url: url, data: Math.random() } resolve(res); }, 1000) }) } getDataAsync('/page/1?param=123') .then(res1 => { console.log(res1); return getDataAsync(`/page/2?param=${res1.data}`); }) .then(res2 => { console.log(res2); return getDataAsync(`/page/3?param=${res2.data}`); }) .then(res3 => { console.log(res3); })
五、generator函数
优点:函数体内外的数据交换、错误处理机制。
缺点:流程管理不方便,何时执行第一阶段,何时执行第二阶段。generator函数不能自动执行,Thunk函数或者co模块用于实现generator函数的自动执行。
function getDataAsync (url) { return new Promise((resolve, reject) => { setTimeout(() => { var res = { url: url, data: Math.random() } resolve(res); }, 1000) }) } function * getData () { var res1 = yield getDataAsync('/page/1?param=123'); console.log(res1); var res2 = yield getDataAsync(`/page/2?param=${res1.data}`); console.log(res2); var res3 = yield getDataAsync(`/page/2?param=${res2.data}`); console.log(res3)); } var g = getData(); g.next().value.then(res1 => { g.next(res1).value.then(res2 => { g.next(res2).value.then(() => { g.next(); }) }) })
// 封装一个执行器 function run (gen) { var g = gen(); function next (data) { var res = g.next(data); if (res.done) return res.value; res.value.then((data) => { next(data); }) } next(); } run(getData);
六、async函数
优点:内置执行器、更好的语义、更广的适用性、返回的是promise、结构清晰。
缺点:错误处理机制
function getDataAsync (url) { return new Promise((resolve, reject) => { setTimeout(() => { var res = { url: url, data: Math.random() } resolve(res) }, 1000) }) } async function getData () { var res1 = await getDataAsync('/page/1?param=123') console.log(res1) var res2 = await getDataAsync(`/page/2?param=${res1.data}`) console.log(res2) var res3 = await getDataAsync(`/page/2?param=${res2.data}`) console.log(res3) }