Promise,Generator,async/await学习总结基本用法
promise
首先,
promise是一种更优的异步编程解决方案,如果我们直接使用传统的回调方式去解决异步流程,就会避免不了大量的回调函数嵌套,形成
回调地狱,
ajax.get(url,function(data1){ ajax.get(url,data1,function(data2){ ajax.get(url,data2,function(data3){ ajax.get(url,data3,function(data4){ //...形成回调地狱 }) }) }) })
为了解决回调地狱的问题,commonjs社区率先提出了promise规范,在ESMA2015中被标准化成为了语言规范。
promise就是一个对象,用来表示一个异步任务,结束以后是成功还是失败。
promise一共有三个状态,
pending(待定状态),
fulfilled(成功状态),
rejected(失败状态)。
状态只能有pending到fulfilled,或者pending到rejected,且状态是不可逆的。
promise中有一个then方法,用来接收回调后的结果,then方法中有两个参数,第一个参数是
成功的回调,第二个参数是
失败的回调。
基本用法:
const promise = new Promise((resolve,reject)=>{ //这里用于兑现承诺 resolve("成功拉!!") // 兑现成功 //reject(new Error("失败拉!!")) // 兑现失败 }) promise.then((value)=>{ console.log(value) //输出的成功的值 },error=>{ //console.log(error) //输出的失败的值 })
promise配合ajax使用案列:
//封装ajax function ajax(url){ return new Promise(function(resolve,reject){ var xhr = new XMLHttpRequest() xhr.open('GET',url) xhr.responseType ='json' xhr.onload=function(){ if(this.status===200){ //代表成功 resolve(this.response) }else{ reject(new Error(this.statusText)) } } xhr.send() }) } //使用 ajax('/api/test.json') .then(data=>{ console.log(data) //请求成功的结果 },reason=>{ console.log(reason) //请求失败的原因 })
promise的链式调用
用来解决回调地狱的问题,是我们的代码更加的扁平化。
上面的代码可以这样使用:
//使用 ajax('/api/test.json') .then(data=>{ console.log(data)//请求成功的结果 //promise 对象的then方法会返回一个全新的peomise对象 return ajax('/api/test2.json') //返回第二个url请求的结果 },reason=>{ console.log(reason) //第一个url错误的捕获 }) //后面的then方法就是为上一个then返回的promise注册回调 .then((test2)=>{ //前面的then方法的返回值会作为后面then方法的回调的参数 console.log(test2) //输出的为第二个url返回的结果 return ajax('/api/test3.json') //返回第三个url请求的结果 }) .then((test2)=>{ console.log(test2) //输出的为第三个url返回的结果 }) //....
Promise的异常处理
- 我们可以一层一层的捕获:
ajax('/api/test.json') .then(data=>{ console.log(data) return ajax('/api/test2.json') },reason1=>{ console.log(reason1)//捕获url1的请求错误 }) .then((test2)=>{ console.log(test2) return ajax('/api/test3.json') },reason2=>{ console.log(reason2)//捕获url2的请求错误 }) .then((test2)=>{ console.log(test2) },reason3=>{ console.log(reason3)//捕获url3的请求错误 })
- 可以使用promise提供的catch对我们的请求进行捕获
ajax('/api/test.json') .then(data=>{ console.log(data) return ajax('/api/test2.json') }) .catch((reason)=>{ console.log(reason) }) 实际上 catch 方法就相当于我们的then方法的第一个值传入了undefined ajax('/api/test.json') .then(data=>{ console.log(data) return ajax('/api/test2.json') }) .then((undefined,reason)=>{ console.log(reason) })
catch这种方式更适用于
链式调用,它可以捕获到每次then回调的错误结果,我们可以这样用:
ajax('/api/test.json') .then(data=>{ console.log(data) return ajax('/api/test1.json') }) .then(data=>{ console.log(data) return ajax('/api/test2.json') }) .catch((reason)=>{ console.log(reason) //1和2有一个发生错误都会捕获到 })
Promise中的静态方法
1.resolve() 快速创建一个成功的对象
Promise.resolve('33') .then((value)=>{ console.log(value) }) 这种写法等同于: new Promise((resolve,reject)=>{ resolve("成功拉!!") })
- reject() 快速创建一个失败的promise对象
Promise.reject(new Error('失败!!!')) .then((value)=>{ console.log(value) })
Promise.all()
promise并行执行的方法
Promise.all()这个方法可以将
多个promise合并为
一个promise统一进行管理
Promise.all()方法接收的是一个
数组,数组中的每一个元素是一个
promise对象,我们可以把这些promise对象看作是一个个的
promise任务,
Promise.all()方法会返回一个
全新的promise对象
当
所有的promise都完成过后,我们返回的全新的promise才会完成,成功的返回的是一个
数组,包含了每一个promise对象成功返回的结果
如果
有一个promise失败了,这个promise.all()就会以
失败结束
var promise = new Promise.all([ ajax('/api/test1.json'), ajax('/api/test2.json'), ajax('/api/test3.json') ]) promise.then(value=>{ //所有的promise都完成过后,才会打印value //value为一个数组 }) .catch(err=>{ console.log(err) //有一个失败就会被捕获到错误信息 })
Promise.race()
Promise.race()也是把多个promise组合到一起的方法
与promise.all()的相同点:
都是传递一个数组
不同点:
promise.all()等待所有任务结束才会结束,Promise.race()只会等待第一个结束的任务,就是说Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态
let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('success') },1000) }) let p2 = new Promise((resolve, reject) => { setTimeout(() => { reject('failed') }, 500) }) Promise.race([p1, p2]).then((result) => { console.log(result) // }).catch((error) => { console.log(error) // 打印的是 'failed' })
Generator
generator(生成器)是ES6标准引入的新的数据类型,它是一种更优的异步编程解决方案。
基本用法:跟普通函数声明时的区别是加了一个*号
function *foo(){ console.log("generator") } foo()
上面的代码并不会执行,我们只有调用foo()函数的next()方法才会执行foo函数
function *foo(){ console.log("generator") } foo().next() // generator
通过yield语句可以在生成器函数内部暂停代码的执行使其挂起,此时生成器函数仍然是运行并且是活跃的,其内部资源都会保留下来,只不过是处在暂停状态。
在迭代器上调用next()方法可以使代码从暂停的位置开始继续往下执行。
function *foo(){ const res = yield "keke" console.log(res) //ff next方法传递过来的值 } } const generator = foo() const result = generator.next() //result表示接收到的值 console.log(result)//{ value: 'keke', done: false } generator.next("ff")
用generator进行异步操作处理:
function ajax(url){ return new Promise(function(resolve,reject){ var xhr = new XMLHttpRequest() xhr.open('GET',url) xhr.responseType='json' xhr.onload=function(){ if(this.status===200){ //代表成功 resolve(this.response) }else{ reject(new Error(this.statusText)) } } xhr.send() }) } **使用 generator 处理异步:** function *main(){ //使用try catch捕获异常 try{ const url = yield ajax('/api/test.json') console.log(url) //拿到返回值 }catch(err){ console.log(err) } } const generator = main() const result = generator.next() //result.value是一个promise对象,我们可以调用then方法获取data result.value.then((data)=>{ generator.next(data) },reason=>{ generator.throw(new Error(reason)) //捕获到错误扔出 })
处理多个异步
function* main() { try { const url = yield ajax('/api/test.json') console.log(url) //拿到url返回值 const url2 = yield ajax('/api/test2.json') console.log(url2) //拿到url2返回值 const url3 = yield ajax('/api/test3.json') console.log(url3) //拿到url3返回值 } catch (err) { console.log(err) } } const generator = main() const result = generator.next() result.value.then((data) => { const result2 = generator.next(data) if (result2.done) return result2.value.then((data) => { const result3 = generator.next(data) if (result3.done) return result3.value.then((data) => { generator.next(data) }) }) }, reason => { generator.throw(new Error(reason)) })
上面的代码我们可以写到一个递归函数里面,结束条件是当 reault.done为true的时候结束,对代码进行优化:
const generator = main() const result = generator.next() //封装到getGenerators函数里面, function getGenerators(result){ if(!result.done){ result.value.then(data=>{ getGenerators(generator.next(data)) },err=>{ generator.throw(new Error(reason)) }) } } //调用 getGenerators(result)
async/await
是es2017新增的一个异步处理方案,它是一个语法糖,用起来很简单
用法如下:
//在函数前面加async async function main() { try { //await代表等待 const url = await ajax('/api/test.json') console.log(url) //拿到url返回值 const url2 = await ajax('/api/test2.json') console.log(url2) //拿到url2返回值 const url3 = await ajax('/api/test3.json') console.log(url3) //拿到url3返回值 } catch (err) { console.log(err) } } main() ``
- ES6总结--Promise 、Generator 、Async/Await
- Promise ,async/await 基本用法
- Beetl学习总结(2)——基本用法
- Callback Promise Generator Async-Await 和异常处理的演进
- Callback Promise Generator Async-Await 和异常处理的演进_1
- 利用ES6中Promise的用法及 ES7中的async await解决异步函数顺序执行的回调地狱问题
- Callback Promise Generator Async-Await 和异常处理的演进
- Promise / generator / async / await 整理
- ES6 学习之promise 基本用法
- Promise, Generator, async/await的渐进理解
- Promise的学习笔记3——async与await、宏队列与微队列
- promise,async await ,generator的区别和nextTick , setImmedate的关系
- c++构造函数学习总结(基本用法)
- Elasticsearch学习总结二 elasticSearch一些基本用法
- Solr学习总结(五)SolrNet的基本用法及CURD
- Promise和Async/Await用法整理
- async 和await的结合promise用法
- async/await基本理解及项目案例(结合Promise)
- 关于Promise,Generator,async / await 对异步的处理
- 学习Markdown 基本用法总结