标签:异步任务 对象 订阅模式 rip tin 统一 线程 timeout http
getData
方法,用于异步获取数据,第一个参数为请求的 url
地址,第二个参数是回调函数,如下: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) }) }) })
通过上面的代码可以看出,第一次请求的 url 地址为: /page/1?param=123 ,返回结果为 res1 。
第二个请求的 url 地址为: /page/2?param=${res1.data} ,依赖第 一次请求的 res1.data ,返回结果为 res2`。
第三次请求的 url 地址为: /page/3?param=${res2.data} ,依赖第二次请求的 res2.data ,返回结果为 res3 。
由于后续请求依赖前一个请求的结果,所以我们只能把下一次请求写到上一次请求的回调函数内部,这样就形成了常说的:回调地狱。
我们假定,存在一个”信号中心”,某个任务执行完成,就向信号中心”发布”( publish )一个信号,其他任务可以向信号中心”订阅”( subscribe )这个信号,从而知道什么时候自己可以开始执行。这就叫做”发布/订阅模式”(publish-subscribe pattern),又称”观察者模式”(observer pattern)
jQuery.subscribe("done", f2);
function f1(){ setTimeout(function () { // f1的任务代码 jQuery.publish("done"); }, 1000); }
jQuery.publish("done")
的意思是,f1
执行完成后,向”信号中心"jQuery
发布"done"
信号,从而引发f2的执行。 此外,f2完成执行后,也可以取消订阅(unsubscribe
)jQuery.unsubscribe("done", f2);
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) })
getDataAsync 方法不变,如下
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) }
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 方法用来自动运行异步的 Generator 函数,其实就是一个递归的过程调用的过程。这样我们就不必手动执行 Generator 函数了。 有了 run 方法,我们只需要这样运行 getData 方法
run(getData)
这样,我们就可以把异步操作封装到 Generator 函数内部,使用 run 方法作为 Generator 函数的自执行器,来处理异步。其实我们不难发现, async/await 方法相比于 Generator 处理异步的方式,有很多相似的地方,只不过 async/await 在语义化方面更加明显,同时 async/await 不需要我们手写执行器,其内部已经帮我们封装好了,这就是为什么说 async/await 是 Generator 函数处理异步的语法糖了
标签:异步任务 对象 订阅模式 rip tin 统一 线程 timeout http
原文地址:http://www.cnblogs.com/7766evr/p/7577213.html