敞开生长之旅!这是我参与「日新计划 12 月更文应战」的第20天,点击查看活动概况第26篇文

Promise根底

Promise根底

一、Promise定义

Promise:许诺者形式:它是ES6新增的一个内置类,基于Promise能够有效管理”异步编程”,避免回调地狱

语法

executor函数

  • letp=newPromise([executor])语法

    • p是它的实例

    • [executor]是一个函数,传递的不是函数会报错

p.proto===Promise.prototype[所属类的原型]

  • 实例私有特点

    • [[PromiseState]]:”pending”

      • promise实例的状况有三种

        • pending准备状况

        • fulfilled/resolved成功状况

        • rejected失利状况

      • 最初的状况是pending,后期基于某些操作能够把状况改变为fulfilled或许rejected

      • (可是一但状况变为成功或许失利,则再也不能修改其状况了)

    • [[PromiseResult]]:undefined

      • [[PromiseResult]]寄存的是成功的成果或许失利的原因!
  • 实例公有特点

then/catch/finally/Symbol.toStringTag=”Promise” [原型上]

Promise根底

二、状况改完有什么用

  • 基于then能够寄存两个函数p.then(onfulfilled,onrejected)

  • 当咱们把状况修改为fulfilled成功态,则会把onfulfilled这个函数履行,相反,咱们把状况修改为rejected失利态,则会把onrejected这个函数履行…

  • 并且会把[[PromiseResult]]作为实参值,传递给onfulfilled/onrejected

三、怎么改状况

  • newPromise的时分,会立即把传递进来的executor[许诺履行人]函数履行,并且会给executor传递两个实参进来

咱们会用两个形参变量接纳resolve/reject,并且值是两个函数

  • 当咱们履行resolve,promise实例状况变为fulfilled成功,传递的值便是成功的成果,赋值给[[PromiseResult]];

同理,只需把reject履行,promise实例状况变为rejected失利,传递的值便是失利的原因!

  • 假如executor函数履行报错了,则实例的状况也是rejected失利,失利原因是便是错误信息!

newPromise发生的实例,他的状况是成功仍是失利,取决于“resolve/reject履行或许executor履行是否报错”

//========================>根底语法
let p=new Promise(function exector(resolve,reject){
	 console.log(1);//先输出1
   resolve('OK');//promise实例状况变为fulfilled 
});
console.log(p);
//p.then(onfulfilled,onrejected)
p.then(function onfulfilled(result){
		//当状况为fulfilled的时分 会履行此函数
  	//result 寄存的是成功成果 OK
},function onrejected(reason){
	 //当状况为rejected的时分,会履行此函数
   //reason 失利的原因
});

四、Promise的then

new Promise((resolve, reject) => {
    $.ajax({
        url: './api/data1.json',
        success(result) {
            resolve(result); //成功的时分把=》实例状况成功
        },
        error(reason) {
            reject(reason); 
        }
    });
}).then(result => {
    console.log('恳求成功', result);//成功做什么
}, reason => {
    console.log('恳求失利', reason);//失利做什么
}); 
//========================setTimeout异步
new Promise((resolve, reject) => {
    setTimeout(() => {
        let ran = Math.random();
        if (ran > 0.5) resolve('OK');
        reject('NO');
    }, 1000);
}).then(result => {
    console.log('恳求成功', result);
}, reason => {
    console.log('恳求失利', reason);
}); 

4.1 屡次.then

咱们能够基于“promise实例.then”寄存多个onfulfilled/onrejected办法,状况变为成功或许失利,

寄存的每一个对应的办法都会被履行

let p1 = new Promise((resolve, reject) => {
    resolve(100);//实例状况变为成功
});
p1.then(result => {
    console.log(`成功:${result}`);//输出成功,100
}, reason => {
    console.log(`失利:${reason}`);
});
p1.then(result => {
    console.log(`成功:${result}`);//输出成功,100
}, reason => {
    console.log(`失利:${reason}`);
}); 

4.2 newPromise发生的是实例 &履行then办法回来的实例

  • newPromise发生的实例,他的状况是成功仍是失利,取决于“resolve/reject履行或许executor履行是否报错”

  • 每一次履行THEN办法,不只寄存了onfulfilled/onrejected办法,并且还会回来一个“全新的promise实例”

    • 新实例p2的状况和值由谁来决议呢?

      • 首先看回来值是否是一个新的Promise实例

      • 不管onfulfilled/onrejected这两个办法履行的是哪一个,咱们只看履行是否报错;

        • 假如报错,则p2的状况是失利态rejected,值是报错原因!

        • 假如不报错,则p2的状况是成功态fulfilled,值是函数的回来值!

let p1 = new Promise((resolve, reject) => {
    reject(0);
});
let p2 = p1.then(result => {
    console.log(`成功:${result}`);
    return 1000;
}, reason => {
    console.log(`失利:${reason}`); //失利 0 //没有报错代码 所以新实例的状况为成功
    return -1000;
});
let p3 = p2.then(result => {
    console.log(`成功:${result}`); //成功 -1000
    throw new Error('xxx');//由于有错误信息,所以这个回来的实例是失利状况
}, reason => {
    console.log(`失利:${reason}`);
});
p3.then(result => {
    console.log(`成功:${result}`);
}, reason => {
    console.log(`失利:${reason}`); //失利 Error:xxx //失利就会履行reason
});

4.3 .then 回来值是一个新的promise实例的特殊状况

特殊状况:咱们之前说,不管onfulfilled/onrejected履行,只需不报错,则新实例p2的状况便是成功,只需报错便是失利…可是这里有一个特殊的状况:“履行不报错,可是回来值是一个新的promise实例,这样回来值的这个promise实例是成功仍是失利,直接决议了p2是成功仍是失利”

let p1 = new Promise((resolve, reject) => {
    resolve(100);
});
let p2 = p1.then(result => {
    console.log(`成功:${result}`); //成功 100
    return new Promise((resolve, reject) => reject(-1000)); //履行了reject 所以状况为失利
}, reason => {
    console.log(`失利:${reason}`);
    return -1000;
});
p2.then(result => {
    console.log(`成功:${result}`);
}, reason => {
    console.log(`失利:${reason}`); //失利:-1000
});
let p1 = new Promise((resolve, reject) => {
    reject(0);//履行了失利的办法
});
let p2 = p1.then(result => {
    console.log(`成功:${result}`);
    return new Promise((resolve, reject) => reject(-1000));
}, reason => {
    console.log(`失利:${reason}`); //失利:0 //p1履行的是reject
    return new Promise((resolve, reject) => resolve(1000)); //成功
});
p2.then(result => {
    console.log(`成功:${result}`); //成功:1000
}, reason => {
    console.log(`失利:${reason}`);
}); 

五、Promise的then链机制

Promise根底

Promise中的then链机制:由于每一次.then都会回来一个新的promise实例,所以咱们就能够持续.then下去了

并且由于实例诞生的方式不同,所以状况判断标准也不同

第一类 new Promise 出来的实例

  • 履行的是resolve仍是reject决议状况
  • executor函数履行是否报错

第二类 :. then 回来的新实例

.then履行会回来一个全新的promise实例“p2”:不管是then中的onfulfilled仍是onrejected履行

  • 首先看回来值是否为新的promise实例,

    • 假如回来的是新的promise实例,则新的promise实例的状况和值,直接决议了.then回来的实例的状况和值

    • 假如不是,则只看履行是否报错「不报错状况便是成功,值便是函数回来值;报错则状况便是失利,值便是失利原因」

第三类 :把Promise当做目标

  • Promise.resolve(100)回来一个状况是成功,值是100的新promise实例【值便是你传递实参进来的实参信息】

  • Promise.reject(0)回来一个状况是失利,值是0的新promise实例

只需实例的状况和值咱们分析好,则.then(onfulfilled,onrejected)寄存的办法,哪一个履行咱们就知道了

let p1 = new Promise((resolve, reject) => {
    resolve(1);//更改p1的状况
    reject(0);
});
let p2 = p1.then(function onfulfilled(result) {
   //履行onfulfilled =>没有报错 没有回来值 则p2的状况是成功 值是undefined
}, function onrejected(reason) {
});
p2.then(function onfulfilled(result) {
   	console.log(result);//成果是undefined
}, function onrejected(reason) {
}); 

思考题

Promise.resolve(100).then(result => {
    console.log(`成功:${result}`);//100
    return result / 10;
}, reason => {
    console.log(`失利:${reason}`);
    return Promise.resolve(200);
}).then(result => {
    console.log(`成功:${result}`);//10
    return Promise.reject(300);
}, reason => {
    console.log(`失利:${reason}`);
    return reason / 20;
}).then(result => {
    console.log(`成功:${result}`);
    return 0;
}, reason => {
    console.log(`失利:${reason}`);//300
    return 1;
}).then(result => {
    console.log(`成功:${result}`);//成功1
}, reason => {
    console.log(`失利:${reason}`);
});

Promise根底

Promise.resolve(Promise.reject(100)); //传递的值是失利的promise实例
// 状况:fulfilled
// 值:新的实例 -> 状况:rejected  值:100 */
Promise.resolve(10).then(result => {
    console.log(`成功:${result}`); //成功 10
    return Promise.resolve(Promise.reject(100));
   //假如实例的状况是成功状况,需要把它的值再次处理一遍,以最终一个值处理的成果为准
}).then(result => {
    console.log(`成功:${result}`);
}, reason => {
    console.log(`失利:${reason}`); //失利:100
}); 
//===========================
Promise.resolve(10).then(result => {
    console.log(`成功:${result}`); //成功:10
    return Promise.reject(Promise.resolve(100));
}).then(result => {
    console.log(`成功:${result}`);
}, reason => {
    console.log(`失利:${reason}`); //失利:[object Promise]
});

以上总结:假如履行onfulfilled或许onrejected的时分,回来的值是是一个promise实例“@P”,

咱们之前说“@P”是成功仍是失利,直接决议了“p2(.then回来的新实例)”是成功仍是失利…可是这样是不严谨的,

  • 按照官方标准要求:

    • 假如@P是成功状况,需要把它的值再次处理一遍…

    • 假如@P是失利的,直接认定为失利的状况,不需要把失利的值再次处理…

5.1 then链的穿透性(顺延)

正常状况下,.then的时分会传递两个函数onfulfilled/onrejected,可是有些时分,咱们是不传递其中的某个函数的,这种状况下咱们需要采取“顺延策略”:找到下一个then中对应状况的函数履行

例如:.then(null,onrejected)【只处理失利】或许.then(onfulfilled)【只处理成功】

Promise.reject(0).then(result => {
    console.log(`成功:${result}`);
    return 1;
}).then(result => {
    console.log(`成功:${result}`);
    return 2;
}).then(result => {
    console.log(`成功:${result}`);
    return 3;
}, reason => {
    console.log(`失利:${reason}`); //失利:0
});
//==================
Promise.resolve(100).then(result => {
    console.log(`成功:${result}`); //成功:100
    throw '我失利了'; //自己抛出异常
}).then(result => {
    console.log(`成功:${result}`);
    return 2;
}).then(result => {
    console.log(`成功:${result}`);
    return 3;
}, reason => {
    console.log(`失利:${reason}`); //失利:我失利了 顺延至最终一个reason
});
//======================
Promise.resolve(100).then(result => {
    console.log(`成功:${result}`); //成功:100
    return 1;
}).then(result => {
    console.log(`成功:${result}`); //成功:1
    return Promise.reject('NO');
}).then(null, reason => {
    console.log(`失利:${reason}`); //失利:NO
}); 

5.2 Promise.catch

.catch(onrejected)相当于==>.then(null,onrejected)

实在项目中,咱们常常:then中只传递onfulfilled,处理状况是成功的工作;在then链的结尾设置一个catch,处理失利的工作(依托于then链的穿透机制,无论最开始仍是哪个then中,呈现了让状况为失利的状况,都会顺延到最结尾的catch部分进行处理)

Promise.resolve(100).then(result => {
    console.log(`成功:${result}`); //成功:100
    return 1;
}).then(result => {
    console.log(`成功:${result}`); //成功:1
    return Promise.reject('NO');
}).catch(reason => {
    console.log(`失利:${reason}`); //失利:NO
});