为什么要用Promise?
第一:
相对于传统的纯回调函数时间上更灵活。 获取到了数据可以晚点再执行回调,3s获得了数据,但是5s之后再执行回调可以,而传统函数必须再启动异步任务前就指定好回调函数,一旦拿到结果就马上回调了
第二:
支持链式调用,支持解决回调函数地狱问题。回调地狱是回调函数的嵌套,上一个函数的结果作为下一个函数的条件
链式调用时候就可以解决这个问题,并且只要写一个catch来进行最后的错误回调
一个Promise对应一个异步任务
回调地狱的终极解决方法:因为promise还有回调函数
使用Promise
excuter是同步回调,异步操作写在excuter里面
产生Promise 的语法糖
const p1 = new Promise((resolve, reject) => {
resolve(1)
})
p1.then(value => {
console.log(value); //1
})
const p2 = Promise.resolve(2).then(value => {
console.log(value); //2
})
const p3 = Promise.reject(3).catch(reason => {
console.log(reason);
})
const pAll=Promise.all([p1,p2,p3..]) 返回也是promise 只有数组里面的所有promise成功才成功
同步操作 直接return 异步操作返回的是promise对象,包括在promise对象中
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 3000)
})
const p2 = Promise.resolve(2)
//const p3 = Promise.reject(3) //对reject 进行回调的时候用then后 会影响all使用
const pAll = Promise.all([p1, p2])
pAll.then(values => {
console.log("All onResolve", values);
}, reason => {
console.log("All Onreject", reason); //3 哪个导致失败
})
注意用Promise.all() 来处理回调的时候,数组中的p1,p2不能再有自己的回调,如p1有自己的成功回调,那整体的all的成功就失效了 有自己的失败回调 那Promise.all()的失败回调就失效
注意Promise.all()传入的是promise数组,打印出来的values与promise执行先后无关,只与传入数组的顺序有关 用定时器做了验证
values:
Promise.race()
Promise.race([p1, p2, p3]).then(value => {
console.log('race', value);
}, reason => {
console.log('race', reason);
})
传入的数组中哪个先执行返回状态就执行哪个promise 的回调 假如p2最快产生失败的回调 那race方法就是调用失败的回调
当promise状态还是peding状态的时候 就会报错
const pp = new Promise((resolve, reject) => {
throw 5;
}).then(null, reason => {
console.log(reason); //5
})
这种学法的then一个状态多个回调,直接在后面.then 就不能多个回调
先指定了回调 后改变状态时,回调函数先保存起来等代状态的改变,如果将定时器去掉就是先指定状态后改变回调函数,这样就不用保存回调,异步执行函数
先改变状态,后执行回调还可以将then方法的定时器设置的时间长点
.then返回的状态,是由回调函数的执行结果决定
异常穿透就是相当于 有reason=>{throw reason} 将错误传递下来
注意不能写 reason=>reason 这样 就是会默认调用成功的调用,就到不了catch()里面去
也不能写 reason=>throw reason 这样相当于return throw reason 也是错误的 抛出错误不能有return
catch() 处理完返回的也是promise对象 .then() 默认是 进行正确的回调
如果catch 将错误抛出来 那才会进行失败的回调
或者 return Promise.reject(reason);
或者 : 包裹一个Promise对象抛出来
中断Promise 链:
如果 return new Promise(()=>{}) 返回的Promise 就一直是pendding状态,后面的then 要根据状态来执行成功或者失败的回调,所以一直在等待 ,这就中断了
ES6向外暴露模块
export function foo(){}
统一以对象的形式暴露 export {foo,foo2},
对应引入就是以对象的形式引入 import {foo,foo2} from ‘…’
默认暴露 只能有一个默认暴露 export default { foo () {…}}
引入 方法 import moudle from ‘被暴露出来的地址’ moudle 是变量,随便定义 引用 : moudle.foo();
ES5 暴露自定义模块
(function(window) {
function Promise() {
}
window.Promise = Promise; //向外暴露Promise
})(window)
require() 方法 导入 module.exports 导出的部分
var app = {
name: 'app',
version: '1.0.0',
sayName: function(name){
console.log(this.name);
}
}
module.exports = app;
var app = require('./app.js');
app.sayName('hello');//hello 拿到的就是模块本身
import 是结构过程并且是编译时执行 必须写在文件顶部
require 是赋值过程中执行的,是异步加载,可以在任何地方
明天 :自定义(手写)Promise