一篇文章彻底搞懂es6 Promise

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

var promise = new Promise(function(resolve, reject) { // ... some code if (/* 异步操作成功 */){ resolve(value); } else { reject(error); } });

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的方式对返回结果进行处理

var getJSON = function(url){ return new Promise((resolve, reject)=>{ var client = new XMLHttpRequest(); client.open('GET', url); client.onreadystatechange = callback; client.send(); function callback(){ if(this.readyState !== 4) return; if(this.status === 200){ resolve(this.response) }else{ reject(new Error(this.statusText)) } } }) } getJSON('/api/getList').then(function(data){ //获取请求的数据 }, function(err){ //请求失败错误处理 });

catch
p.catch()用于处理promise中rejected状态的回调,与p.then(resolveFn, rejectFn)中 rejectFn的作用相同

var p = new Promise(function(resolve, reject){ ... }); p.then(function(){}, function(){}); //等同于 p.then(function(){}).catch(function(){});

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函数返回的错误信息,也更接近同步的写法

// bad new Promise(function(resolve, reject){}).then(resolveFn, rejectFn) // good new Promise(function(resolve, reject){}).then(resoveFn).catch(rejectFn) Promise all与race

Promise.all([]) 与 Promise.race([])

接收一个数组做为参数,参数中的每个元素为promise实例,

如果元素不是promise实例,则会调用Promise.resolve()转换为promise的实例

将多个promise对象包装为一个新的promise对象

1、Promise.all()

Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wssjjx.html