ES6中 Promise总结

ES6中 Promise总结

提示:如果你还不太懂js中的同步代码和异步代码 请参考此扩展阅读

1.什么是Promise

Promise 是ES6中新增的异步编程解决方案,在代码中的表现是一个对象.

// 需求: 从网络上加载3个资源, 要求加载完资源1才能加载资源2, 加载完资源2才能加载资源3
//       前面任何一个资源加载失败, 后续资源都不加载
function request(fn) {
    setTimeout(function () {
        fn("拿到的数据");
    }, 1000);
}
request(function (data) {
    console.log(data, 1);
    request(function (data) {
        console.log(data, 2);
        request(function (data) {
            console.log(data, 3);
        });
    });
});

/*
2.promise作用
企业开发中为了保存异步代码的执行顺序, 那么就会出现回调函数层层嵌套
如果回调函数嵌套的层数太多, 就会导致代码的阅读性, 可维护性大大降低
promise对象可以将异步操作以同步流程来表示, 避免了回调函数层层嵌套(回调地狱)

*/
function request() {
  return new Promise(function (resolve, reject) {
      setTimeout(function () {
          resolve("拿到的数据");
      }, 1000);
  });
}
request().then(function (data) {
  console.log(data, 1);
  return request();
}).then(function (data) {
  console.log(data, 2);
  return request();
}).then(function (data) {
  console.log(data, 3);
});

2.Promise的基本使用

  1. 什么是Promise?

    Promise是ES6中新增的一个对象,
    通过Promise就可以实现 用同步的流程来表示异步的操作
    通过Promise就可以 避免回调函数层层嵌套(回调地狱)问题

  2. 如何创建Promise对象?

    new Promise(function(resolve, reject){});
    promise对象不是异步的, 只要创建promise对象就会立即执行存放的代码

  3. Promise是如何实现 通过同步的流程来表示异步的操作的?

    promise对象是通过状态的改变来实现的, 只要状态发生改变就会自动触发对应的函数

  4. Promise对象三种状态

    pending: 默认状态,只要没有告诉promise任务是成功还是失败就是pending状态
    fulfilled(resolved): 只要调用resolve函数, 状态就会变为fulfilled, 表示操作成功
    rejected: 只要调用rejected函数, 状态就会变为rejected, 表示操作失败
    注意点: 状态一旦改变既不可逆, 既从pending变为fulfilled, 那么永远都是fulfilled
    即从pending变为rejected, 那么永远都是rejected

  5. 监听Promise状态改变

    可以通过函数来监听状态的变化
    resolved --> then()
    rejected --> catch()

let promise = new Promise(function (resolve, reject) {
        console.log("1");
        reject();
        // resolve();
    });
    promise.then(function () {
        console.log("then");
    });
    promise.catch(function () {
        console.log("catch");
    });

3.then方法详解

then方法接收两个参数,
第一个参数是状态切换为成功时的回调,
第二个参数是状态切换为失败时的回调

let promise = new Promise(function (resolve, reject) {
    // resolve(); // 将状态修改为成功
    reject(); // 将状态修改为失败
});
promise.then(function () {
    console.log("成功");
}, function () {
    console.log("失败");
});

then方法
在修改promise状态时, 可以传递参数给then方法中的回到函数

// resolve = success, reject = error;
let promise = new Promise(function (resolve, reject) {
    // resolve("111"); // 将状态修改为成功 success("111");
    reject("aaa"); // 将状态修改为失败  error("aaa");
});
// promise.then(function (data) {
//     console.log("成功", data);
// }, function (data) {
//     console.log("失败", data);
// });
function success(data) {
    console.log(data);
}
function error(data) {
    console.log(data);
}
promise.then(success, error);

then方法
同一个promise对象可以多次调用then方法,
当该promise对象的状态时所有then方法都会被执行

let promise = new Promise(function (resolve, reject) {
    // resolve(); // 将状态修改为成功
    reject(); // 将状态修改为失败
});
promise.then(function () {
    console.log("成功1");
}, function () {
    console.log("失败1");
});
promise.then(function () {
    console.log("成功2");
}, function () {
    console.log("失败2");
});

then方法
then方法每次执行完毕后会返回一个新的promise对象

let promise = new Promise(function (resolve, reject) {
    resolve(); // 将状态修改为成功
    // reject(); // 将状态修改为失败
});
let p2 = promise.then(function () {
    console.log("成功1");
}, function () {
    console.log("失败1");
});
console.log(p2);
console.log(promise === p2);//false

then方法
可以通过上一个promise对象的then方法给下一个promise对象的then方法传递参数
注意点:
无论是在上一个promise对象成功的回调还是失败的回调传递的参数,
都会传递给下一个promise对象成功的回调

let promise = new Promise(function (resolve, reject) {
    // resolve("111"); // 将状态修改为成功
    reject("aaa"); // 将状态修改为失败
});
let p2 = promise.then(function (data) {
    console.log("成功1", data);
    return "222";
}, function (data) {
    console.log("失败1", data);
    return "bbb";
});
p2.then(function (data) {
    console.log("成功2", data);
}, function (data) {
    console.log("失败2", data);
});

then方法
如果then方法返回的是一个Promise对象, 那么会将返回的Promise对象的
执行结果中的值传递给下一个then方法

let promise = new Promise(function (resolve, reject) {
    resolve("111"); // 将状态修改为成功
    // reject("aaa"); // 将状态修改为失败
});
let ppp = new Promise(function (resolve, reject) {
    // resolve("222"); // 将状态修改为成功
    reject("bbb"); // 将状态修改为失败
});
let p2 = promise.then(function (data) {
    console.log("成功1", data);
    return ppp;
}, function (data) {
    console.log("失败1", data);
    return "bbb";
});
p2.then(function (data) {
    console.log("成功2", data);
}, function (data) {
    console.log("失败2", data);
});

catch方法详解

catch方法与then方法所讲的注意点基本一致,以下只说出catch独有的注意点

/*
0.catch方法
catch 其实是 then(undefined, () => {}) 的语法糖
* */

let promise = new Promise(function (resolve, reject) {
    // resolve(); // 将状态修改为成功
    reject(); // 将状态修改为失败
});
promise.catch(function () {
    console.log("abc");
});

/*
2.catch方法
注意点: 如果需要分开监听, 也就是通过then监听成功通过catch监听失败
那么必须使用链式编程, 否则会报错
* */
let promise = new Promise(function (resolve, reject) {
    // resolve(); // 将状态修改为成功
    reject(); // 将状态修改为失败
});
 promise.then(function () {
     console.log("成功");
 }).catch(function () {
     console.log("失败");
 });
/*  报错
promise.then(function () {
    console.log("成功");
});
promise.catch(function () {
    console.log("失败");
});
*/

/*
3.catch方法
不使用链式编程的原因是
1.如果promise的状态是失败, 但是没有对应失败的监听就会报错
2.then方法会返回一个新的promise, 新的promise会继承原有promise的状态
3.如果新的promise状态是失败, 但是没有对应失败的监听也会报错
* */
let promise = new Promise(function (resolve, reject) {
    // resolve(); // 将状态修改为成功
    reject(); // 将状态修改为失败
});
let p2 = promise.then(function () {
    console.log("成功");
});
console.log(p2);
promise.catch(function () {
    console.log("失败1");
});
p2.catch(function () {
    console.log("失败2");
});

/*
    6.catch方法
    和then方法第二个参数的区别在于, catch方法可以捕获上一个promise对象then方法中的异常
    * */
    let promise = new Promise(function (resolve, reject) {
        resolve();
    });
    // promise.then(function () {
    //     console.log("成功");
    //     xxx
    // }, function () {
    //     console.log("失败");
    // });
    promise.then(function () {
        console.log("成功");
        xxx
    }).catch(function (e) {
        console.log("失败", e);
    });

promise应用场景练习

/*
需求:
一次加载一张图片添加到body中. 前面图片加载失败后面图片不加载
*/
let arr = [
    "http://www.xxx.com/picture_1.png",
    "http://www.xxx.com/picture_2.png",
    "http://wwww.xxx.com/files/picture_3.png"
];
function loadImage(url) {
    return new Promise(function (resolve, reject) {
       let oImg = new Image();
       oImg.src = url;
       oImg.onload = function () {
           resolve(oImg);
       }
       oImg.onerror = function () {
           reject("图片加载失败");
       }
    });
}
loadImage(arr[0]).then(function (oImg) {
        // console.log(oImg);
        console.log("1");
        document.body.appendChild(oImg);
        return loadImage(arr[1]);
    }).then(function (oImg) {
        console.log("2");
        // console.log(oImg);
        document.body.appendChild(oImg);
        return loadImage(arr[2]);
    }).then(function (oImg) {
        console.log("3");
        // console.log(oImg);
        document.body.appendChild(oImg);
    }).catch(function (msg) {
        console.log(msg);
    });

promise-all方法

Promise的all静态方法:
1.all方法接收一个数组,
2.如果数组中有多个Promise对象,只有都成功才会执行then方法,并且会按照添加的顺序, 将所有成功的结果重新打包到一个数组中返回给我们.
3.如果数组中不是Promise对象, 那么会直接执行then方法

应用场景: 批量加载, 要么一起成功, 要么一起失败

练习:

/*
需求:
	无序加载图片, 只有所有图片都加载成功才添加, 有一张图片失败都不添加
*/
let arr = [
    "http://www.xxx.com/picture_1.png",
    "http://www.xxx.com/picture_2.png",
    "http://wwww.xxx.com/files/picture_3.png"
];
function loadImage(url) {
    return new Promise(function (resolve, reject) {
        let oImg = new Image();
        let time = Math.random() * 1000;
        // console.log(time);
        setTimeout(function () {
            oImg.src = url;
        }, time);
        // oImg.src = url;
        oImg.onload = function () {
            resolve(oImg);
        }
        oImg.onerror = function () {
            reject("图片加载失败了");
        }
    });
}
Promise.all([loadImage(arr[0]), loadImage(arr[1]),loadImage(arr[2])])
        .then(function (result) {
            // console.log(result);
            result.forEach(function (oImg) {
                document.body.appendChild(oImg);
            });
        })
        .catch(function (e) {
            console.log(e);
        });

promise-race方法

Promise的race静态方法:
1.all方法接收一个数组,
2.如果数组中有多个Promise对象, 谁先返回状态就听谁的, 后返回的会被抛弃
3.如果数组中不是Promise对象, 那么会直接执行then方法

应用场景: 接口调试, 超时处理

场景模拟:

let url = "http://www.xxx.com/picture_1.png";
function loadImage(url) {
    return new Promise(function (resolve, reject) {
        let oImg = new Image();
        setTimeout(function () {
            oImg.src = url;
        }, 5000);
        oImg.onload = function () {
            resolve(oImg);
        }
        oImg.onerror = function () {
            reject("图片加载失败了");
        }
    });
}
function timeout() {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            reject("超时了");
        }, 3000);
    });
}
Promise.race([loadImage(url), timeout()]).then(function (value) {
    console.log("成功", value);
}).catch(function (e) {
    console.log("失败", e);
});
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值