异步就是比较耗时的操做,CPU缓存的速度是最快的,而后是内存,而后是硬盘,因此从硬盘上读取文件是很是慢的,js认为从硬盘上读取文件是一个异步操做;另一种是网络请求,这种也是异步的;操做dom节点也是很是耗时的,但倒是同步操做,由于做为异步来处理比较麻烦。node
promise就是一个承诺,在js中就是承诺过段时间会返回一个结果,而这个过段时间就指的是异步操做。webpack
promise本质上是一个有限状态机,状态机指的是根据特定的条件按照必定的顺序进行转换,并且过程不可逆。每一个promise实例都有三种状态:pending、resolve、reject。在状态机中,须要某些条件才能将本身的状态触发。git
状态只有两种:从初始状态到成功:pending->resolve;从初始状态到失败:pending->reject。promise实例状态机状态的变化会触发promise原型上的then或catch方法的执行github
DOM规范是运行在浏览器上的规范,好比navigator,只在dom上有,在node上没有;而ECMAScript规范,不只在浏览器中可使用,也能够在node.js中使用。web
如何构建一个promiseajax
构建一个promise实例须要给promise构造函数传入一个有两个形参的函数,第一个形参运行后会让promise实例处于resolve状态,因此通常用resove表示成功状态;第二个形参运行后会让promise实例处于reject状态,因此通常用reject表示失败状态。new出来的promise实例,有两个方法(then,catch,then捕获成功的操做,catch捕获失败的操做。),而且能够链式调用。在使用的时候,要将then放在catch的上面,这是由于then里的错误也能够在catch中捕获到,如代码所示:json
let promiseInstance = new Promise((resolve,reject) =>{ setTimeOut(() => { resolve('this is resolve.') }) }) promiseInstance .then((value)=>{console.log(value)}).catch((err)=>{console.error(err)})
promise是处理异步的,而网络请求是异步最多见的场景,因此能够用promise封装一个网络请求的方法,因此不少时候promise的实例是做为函数的返回值是,调用函数后能够对返回值的Promise对象进行相应的操做api
function ajaxPromise(){
return new Promise((resolve,reject) => {
let xhr = new XMLHttpRequest();
xhr.open('get',queryUrl,true);
xhr.send(null);
xhr.onReadyStatechange = () => {
if(xhr.readyState === 4){
if(xhr.status === 200){
resolve(xhr.responseText);
}else{
reject(xhr.responseText)
}
}
}
}) }
ajaxPromise('http://api.github.com/')
.then((value) => {
console.log(value);
})
.catch((err) => {
console.error(err)
})
then与catch的使用promise
状态机的状态是不可逆的,因此执行了resolve方法,就算再执行reject方法,也不会有效果了。浏览器
promise的api
promise实例上的方法
promise.prototype.then()
promise.prototype.catch()
promise构造函数上的方法
promise.all(Array) 返回一个promise,等待参数中全部的promise都处于resolve状态后会触发返回的promise实例的resolve状态
promise.race(Array) 返回一个promise,参数中第一个执行完成的状态决定出发哪一个函数
promise.resolve() 马上返回一个resolve状态的实例
promise.reject() 马上返回一个reject状态的实例
let promise1 = new Promise((resolve,reject)=>{ setTimeout(resolve,1000,'success1') }) let promise2 = new Promise((resolve,reject)=>{ setTimeout(resolve,1000,'success12') }) let promise3 = new Promise((resolve,reject)=>{ setTimeout(resolve,1000,'success3') }) Promise.all([promise1, promise2, promise3]).then((value)=>{ console.log(value) }).catch((err)=>{ console.error(err) })
tips:setTimeOut的第三个参数,是第一个函数参数执行的时候,要传入的参数
promise.then的执行时机
promise.resolve是处理异步问题的,因此会先把同步的代码执行完,再执行promise.resolve返回实例的then或catch的代码
而Promise构造函数是同步的,then方法是异步的。setTimeOut的执行时机是最晚的
promise并非处理异步最好的方法,好比回调金字塔的问题并无解决,只是看起来更清晰了。解决异步最好的方法是async
generator
有点像一个函数内部有多个函数,是一个状态机,yield生成
function* genFunc(){ yield 'hello';
yield 'generator';
yield '!'
return 'end'//generator不建议使用return
}
generator返回的不是返回值,也不是一个生成的内容,而是一个迭代器,迭代器是一个可遍历的对象,迭代器有个next方法。经过for-of循环遍历迭代器
连续运行的generator
function* genFunc(initValue){ let first = yield new Promise((resolve,reject)=>{ setTimeOut(resolve,1000,'1'+initValue) }) let second = yield new Promise((resolve,reject)=>{ setTimeOut(resolve,1000,'2-'+first) }) let third = yield new Promise((resolve,reject)=>{ setTimeOut(resolve,1000,'3-'+second) }) let genHandler = genFunc(1) genHandler.next().value. then((value) => { genHandler.next(value).value. then((value) => { then((value) => { console.log(value); }) }) }) }
co库与async函数
import co from 'co'
上述代码中依然有回调金字塔,能够用co库解决
co(genFunc(1)).then((value) => {console.log(value)})//2-11
async至关因而generator+promise+co,是es7的新语法,目前没有浏览器实现,因此须要用webpack+babel编译一下才能够运行。
如何同步异步请求,即两次请求,异步执行,如何在两次请求都执行完成的状况下执行后续程序
function request(content){ setTimeout(()=>{ document.body.append(content) },Math.floor(Math.random()*1000)) //时间控制为不肯定
} request('hello') request('world') //如何在两次request完成后执行代码。可使用promise.all,只要两个异步有一个完成就能够,可使用promise.race
docuement.body.append('finished')
如何处理回调嵌套回调
//珠峰课堂是先去服务端拿取token,而后再去拿课程
fetch('https://ketang.zhufengpeixun.cn/token') .then(response => { response.json().then(tokenJson =>{ const token = tokenJson fetch('https:ketang.zhufengpeixun.cn/course') .then( response =>{ response.json().then(tokenJson =>{ } }) }) })
promise定义:用于异步计算,表明一个当前、将来或永远不可用的值
//promise中的代码段被直接执行了
const promise = new Promise((resolve,reject){ document.body.append('hello') }) const a = () =>{ document.body.append('world') } a(); //执行结果是hello world
//用promise表示一个将来的值
function resolve_example(){ const promise = new Promise((resolve,reject)=>{ document.body.append('start.....'); setTimeout(()=>{//promise表明了一个将来值
resolve('done') },2000) }) return promise; } const promise = resolve_example(); //获得一个将来完成的值,此处data是异步返回的部分
promise.then(data => { document.body.append(data) })
promise有三种状态,当被new出来的时候属于pending状态,使用resolve则是fulfill状态,使用reject则是fail状态
Executor是构造Promise的惟一参数,在promise构造的时候会被立刻执行