Promise,用于解决回调地狱带来的问题,将异步操作以同步的操作编程表达出来,避免了层层嵌套的回调函数。
既然是用来解决回调地狱的问题,那首先来看下什么是回调地狱
var sayhello = function(callback){ setTimeout(function(){ console.log("hello"); return callback(null); },1000); } sayhello(function(err){ console.log("xiaomi"); }); console.log("mobile phone"); 输出结果 mobile phone hello Xiaomi看上面这段代码,假如我们需要对输出内容的顺序进行调整,例如依次打印xiaomi apple huawei ,那么我们之前的做法是怎么样的
var sayhello = function(name, callback){ setTimeout(function(){ console.log("hello"); console.log(name); return callback(null); },1000); } sayhello("xiaomi", function(err){ sayhello("apple", function(err){ sayhello("huawei", function(err){ console.log("end"); }); }); }); console.log("mobile phone");问题很明显,代码层层嵌套,看起来十分的混乱,如果层级代码更多更是难以维护
因此Promise的出现使得我们可以用同步的方式来操作异步代码,解决以上问题
初识promise var getUserInfo = function() { return new Promise(function(resolve) { setTimeout(function() { var user = {name: 'Kerry Wu', age: 31}; resolve(user); }, 3000); }); }; this.getUserInfo().then(function(userInfo) { console.log('userInfo',userInfo);//{ name: 'Hanmeimei', age: 31 } });我们通过new关键词实例化一个Promise对象并返回该对象,然后使用.then的形式获取Promise返回的内容
这里需要注意的是,new Promise 实例化是一个同步的过程,而.then是一个异步的过程,关于同步异步执行顺序 ,先执行同步在执行异步代码
Promise状态1、Pending 进行中 / Resolved 已成功 / Rejected 已失败
resove 将未完成变成已完成 pending => resolved
reject 将未完成变成已失败 pending => rejected
2、then 与 catch
then方法接收两个函数参数,第一个表示resove 已成功的回调,第二个表示reject 已失败的回调
用法如下:
var p = new Promise(function(resolve, reject){ ... }) p.then(function(){}, function(){}) p.then().catch();then,前一个then的返回结果,可以再后一then的回调中获取,如:
var p3 = ()=> new Promise((resolve, reject)=>{ resolve('{"name":"jack", "age":28}') }); p3() .then(res => JSON.parse(res)) .then(data => Object.assign(data, {name:'rose'})) .then(data => console.log(data)) // 输出:{name: "rose", age: 28}异步加载图片
function loadImageAsync(url) { return new Promise(function(resolve, reject) { var image = new Image(); image.onload = function() { resolve(image); }; image.onerror = function() { reject(new Error('Could not load image at ' + url)); }; image.src = url; }); } loadImagesAsync('//img.static.com/xxx.jpg').then(function(img){ //加载成功 显示图片 }, function(err){ //加载失败 提示失败 })异步加载数据
使用promise包装一个异步请,返回一个promise对象,使用then和catch的方式对返回结果进行处理
catch
p.catch()用于处理promise中rejected状态的回调,与p.then(resolveFn, rejectFn)中 rejectFn的作用相同
reject(‘error’) 与 throw new Error(‘…’) 都能被catch捕获
new Promise((resolve, reject) => { throw new Error('some error1'); }).catch(err => console.log(err.message)) // 等同于 new Promise((resolve, reject) => { reject('some error2') }).catch(err => console.log(err))捕获异常
promise对象的错误,具有 冒泡 性质,会一直向后传递,直到被捕获
推荐使用 catch 代替then(null, rejectFn)中的rejectFn,catch可以捕获前面then函数返回的错误信息,也更接近同步的写法
Promise.all([]) 与 Promise.race([])
接收一个数组做为参数,参数中的每个元素为promise实例,
如果元素不是promise实例,则会调用Promise.resolve()转换为promise的实例
将多个promise对象包装为一个新的promise对象
1、Promise.all()
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调