目录
Promise(function(resolve,reject){})
promise.then(function(res){},function(rej){})
Promise(function(resolve,reject){})
首先使用需要通过new Promise(function(resolve,reject){}),Promise()构造函数必须接收一个函数,否则会报错,这个函数会有自动接收2个系统赋值的参数,不定义也会在arguments里接收。新建的对象时会运行function中的代码,新建出来的对象中会有2个系统定义的属性,PromiseState初始为pending,通过在function中调用系统传给function的2个参数来修改,调用resolve()后变为fulfilled,调用reject()后变为rejected。该状态只会改变一次即之后如果还有resolve函数和reject函数都会失去作用。无论调用哪个函数,都会继续走完Promise中的function内容,除非代码出现错误。PromiseResult初始为undefined,通过向resolve()和reject()函数中传入参数改变为参数值。
new Promise((res,rej)=>{
console.log(1);
res('y');
console.log(3)
res('p');
rej()
}).then((res)=>{console.log(res)})
//1
//3
//y
注意function中代码如果有错误,除resolve()在错误行之前,PromiseState为fulfilled,PromiseResult为undefined;其它情况PromiseState都为rejected,PromiseResult为错误信息。其中throw(str)语句相当于发生了错误,其错误信息为str字符串内容。
promise对象调用的方法
这些方法是定义在Promise.prototype上的方法,可以在控制台中直接通过Promise.prototype打印查看。
promise.then(function(res){},function(rej){})
当新建promise对象的function中内容完全运行完后才会运行then方法,根据promise对象的PromiseState状态执行函数:
当为fulfilled或rejected时,执行第一个或第二个function,把PromiseResult传给res或rej。如果执行的函数中没有return新的promise对象,则返回一个新的promise对象,其PromiseResult为返回值,PromiseState为fulfilled;如果返回了新的promise对象,则根据新的对象接收的函数决定PromiseState和PromiseResult的值。注意当不写第二个functin或传入null时,如果promise对象状态位为rejected,那么返回新promise对象的PromiseState和PromiseResult也相同。
当为pending时,不执行任何函数,直接返回一个新的promise对象,PromiseState为pending,PromiseResult为undefined。
promise.catch(function(){})
同promise.then(null,function(rej){})。
promise.finally(function(){})
最后无论怎样都会执行function中内容,返回promise原对象。
Promise上定义好的静态方法
Promise.resolve(js)
相当于new Promise(function(res,rej){res();js};当js为js代码,不同在于js代码如果出错,该语句是会报错,不运行的。当js为字符串时function里为res(js)。
Promise.reject(js)
相当于new Promise(function(res,rej){rej();js};当中js为js代码,不同在于js代码如果出错,该语句是会报错,不运行的。当js为字符串时function里为rej(js)。
Promise.all([p1,p2,...,pn])
接收一个数组,其中p1,p2,...,pn为promise对象,只有p1,p2,...,pn的PromiseState全为fulfilled时,才返回一个PromiseState为fulfilled的新promise对象且此时PromiseResult为一个数组,数组中的每一位是p1,p2,...,pn的PromiseResult。否则为rejected,PromiseResult为p1,p2,...,pn中首先出现PromiseState='rejected'的PromiseResult。
Promise.race([p1,p2,...,pn])
接收一个数组,其中p1,p2,...,pn为promise对象,返回一个新promise对象,它的PromiseState值为p1,p2,...,pn中第一个PromiseState变化的值(变为非pending状态),PromiseResult等于变化的promise对象的PromiseResult值。
超时处理示例
const request = ajax(url);
const timeout = new Promise((res, rej)=>{
setTimeout(()=>rej(new Error('timeout')),500)
}
Promise.race([request,timeout]).then(value=>{
console.log(value);
}).catch(error=>{
console.log(error)
})
作用
用于解决异步回调(回调地狱)问题。
主要原理
Promise对象的then方法是在新建对象Promise()接收的函数完全执行完后才运行。
例子
下面例子能实现First、Second、Third依次输出。注意then方法中要return新的promise对象中包裹Second输出,如果直接then中输出Second,则只能保证First在Second和Third之前输出,无法保证Second和Third的输出顺序,因为then方法只能保证在new Promise接收的function运行完成之后执行,并不能保证then方法中function内容执行和它返回的新promise的对象的then中的function执行顺序。
new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("First");
resolve();
}, 1000);
}).then(function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("Second");
resolve();
}, 4000);
});
}).then(function () {
setTimeout(function () {
console.log("Third");
}, 3000);
});
Promise实现源码
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor (executor) {
try {
executor(this.resolve, this.reject);
} catch (e) {
this.reject(e);
}
}
status = PENDING;
value = undefined;
reason = undefined;
successCallback = [];
failCallback = [];
resolve = value => {
if (this.status !== PENDING) return;
this.status = FULFILLED;
this.value = value;
while(this.successCallback.length) {
this.successCallback.shift()();
}
}
reject = reason => {
if (this.status !== PENDING) return;
this.status = REJECTED;
this.reason = reason;
while(this.failCallback.length) {
this.failCallback.shift()();
}
}
// 默认的参数使then方法能不传参情况下向后传递值
// new promise((res, rej)=>{res(100)}).then().then(v=>{console.log(v)})
then (successCallback = value => value, failCallback = reason => { throw reason;}) {
let promise2 = new MyPromise((resolve, reject) =>{
if (this.status === FULFILLED) {
try {
// 为了能拿到promise2的引用,使用setTimeout将下面代码变为异步代码。
setTimeout(() => {
let x = successCallback(this.value);
// 判断x的值时普通值还是promise对象
// 如果是普通值,直接调用resolve;
// 如果是promise对象,查看promise对象返回的结果再根据promise对象返回的结果决定调用resolve还是reject;
this.resolvePromise(promise2, x, resolve, reject);
},0)
} catch (e) {
reject(e);
}
} else if (this.status === REJECTED) {
try {
setTimeout(() => {
let x = failCallback(this.reason);
this.resolvePromise(promise2, x, resolve, reject);
},0)
} catch (e) {
reject(e);
}
} else {
this.successCallback.push(() => {
try {
setTimeout(() => {
let x = successCallback(this.value);
this.resolvePromise(promise2, x, resolve, reject);
},0)
} catch (e) {
reject(e);
}
});
this.failCallback.push(() => {
try {
setTimeout(() => {
let x = failCallback(this.reason);
this.resolvePromise(promise2, x, resolve, reject);
},0)
} catch (e) {
reject(e);
}
});
}
})
return promise2;
}
resolvePromise(promise2, x, resolve, reject) {
if(promise2 === x) {
// 情况1报错
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
if(x instanceof MyPromise) {
x.then(resolve, reject)
} else {
resolve(x)
}
}
catch(failCallback) {
return this.then(undefined, failCallback)
}
finally (callback) {
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value);
}, reason => {
return MyPromise.resolve(callback()).then(() => { throw reason; });
})
}
static resolve(value){
if (value instanceof MyPromise) {
return value;
} else {
return new MyPromise(resolve => resolve(value))
}
}
static all(array) {
let result = [];
let index = 0;
function addData (key, value, resolve) {
result[key] = value;
index++;
if (index === array.length) {
// 当所有的promise都返回后再resolve出去。
resolve(result);
}
}
return new MyPromise((resolve, reject) => {
for(let i = 0; i < array.length; i++){
let current = array[i];
if (current instanceof MyPromise){
current.then(value => addData(i, value, resolve), reason => reject(reason))
} else{
addData(i, array[i], resolve)
}
}
})
}
}
// 情况1报错
let promise = new Promise((res, rej) => {
res(100)
});
let p1 = promise.then(value => p1)