创建未处理的Promise的最好方法是使用Promise的构造函数,如果只想用Promise表示一个已知的值,编排一个只是简单的给resolve()函数传值的任务毫无意义,有什么替代方案吗?在实际工作中,会遇到编排很多任务依次执行完成之后,对每次执行结果处理,显然会很繁琐。可不可以所有的编排任务,一次被得到响应,然后再对结果做最终处理呢?Promise提供的四个静态方法可以满足以上两个场景下的需求,进而增加代码的可读性。
创建已处理的Promise
如果只想用Promise表示一个已知的值,编排一个只是简单的给resolve()
或reject()
传值的任务显得有点不合事宜。可以用以下两种方法根据特定的值来创建已解决Promise。
-
使用Promise.resolve()
Promise.resolve()
方法只接受一个参数并返回一个完成态的Promise,也就是说不会有任务编排的过程,而且需要项Promise添加一至多个完成处理程序来获取值。例如:let promsie = Promise.resolve(42) promise.then(function (value) { console.log(value) // 42 })
-
使用Promise.reject()
Promise.reject()
创建已拒绝Promise,它与Promise.resolve()
唯一的区别是创建出来的是拒绝态的Promise。例如:let promise = Promise.reject(34) promise.catch(function (value) { console.log(value) // 43 })
Promise.resolve源码
var TRUE = valuePromise(true);
var FALSE = valuePromise(false);
var NULL = valuePromise(null);
var UNDEFINED = valuePromise(undefined);
var ZERO = valuePromise(0);
var EMPTYSTRING = valuePromise('');
function valuePromise (value) {
var p = new Promise(Promise._noop)
p._state = 1
p._value = value
return p
}
Promsie.resolve = function (value) {
// 传入的是Promise对象时,会被直接返回
if (value instanceof Promise) return value
// 传入以下数据类型时,需要调用valuePromise方法返回一个Promise对象
if (value === null) return NULL
if (value === undefined) return UNDEFINED
if (value === true) return TRUE
if (value === false) return FALSE
if (value === 0) return ZERO
if (value === '') return EMPTYSTRING
// value为object或function时
if (typeof value === 'object' || typeof value === 'function') {
try {
var then = value.then
if (typeof then === 'function') {
return new Promise(then.bind(value))
} catch (ex) {
return new Promise(function (resolve, reject) {
reject(ex)
})
}
}
// 以上条件都不符合
return valuePromise(value)
}
}
- 如果向
Promise.resolve()
或Promise.reject()
传入一个Promise,通过if (value instanceof Promise) return value
直接返回Promise对象。 - 传入一个非Promisse的Thenable对象,这些方法会创建一个新的Promise对象,并在then()函数中被调用。传入一个非Promise的Thenable对象时,经过
typeof value === 'object' || typeof value === 'function'
判断,返回一个新的Promise对象,并将Thenable对象的then()
方法作为参数传到新实例化的Promise对象中。举个栗子:
let thenable = {
then: function (resolve, reject) {
resolve('我是thenable对象的输出')
}
}
let p1 = Promise.resolve(thenable)
p1.then(function (value) {
console.log(value) // 我是thenable对象的输出
})
在此示例中,thenable对象作为参数传入时,其实就转化为p1 = new Promise(function (resolve, reject) {resolve(''我是thenable对象的输出'')})
,因此最后结果输出“'我是thenable对象的输出'”。
Promise.reject源码
Promise.reject
的实现过程相对来说简单,只是返回一个Promise实例对象。代码如下:
Promise.reject = function (value) {
return new Promise(function (resolve, reject) {
reject(value)
})
}
响应多个Promise
ECMAScript6提供了Promise.all()
和Promise.race()
两个方法监听多个Promise。
Promise.all
Promise.all()
方法只接受一个参数并返回一个Promise,该参数是一个含有多个受监视Promise的可迭代对象,只有当可迭代对象中所有的Promise都被解决后返回的Promise才会被解决;只有当可迭代对象中所有Promise都被接完成后返回的Promise才会被完成。
let p1 = new Promise(function (resolve, reject) {
resolve(42)
});
let p2 = new Promise(function (resolve, reject) {
resolve(43)
});
let p3 = new Promise(function (resolve, reject) {
resolve(44)
})
let p4 = Promise.all([p1, p2, p3])
p4.then(function (value) {
console.log(Array.isArray(value)) // true
console.log(value[0]) // 42
console.log(value[1]) // 43
console.log(value[2]) // 44
})
所有传入Promise.all()
方法的Promise只要有一个被拒绝,那么返回的Promise没等所有Promise都完成就立即被拒绝。例如:
let p1 = new Promise(function (resolve, reject) {
reject(42)
});
let p2 = new Promise(function (resolve, reject) {
reject(43)
});
let p3 = new Promise(function (resolve, reject) {
resolve(44)
})
let p4 = Promise.all([p1, p2, p3])
p4.then(function (value) {
console.log(Array.isArray(value)) // true
console.log(value[0])
console.log(value[1])
console.log(value[2])
}).catch(function (value) {
console.log(value) // 42
})
Promise.race
Promise.race()
方法接受一个含多个受监视Promise的可迭代对象作为唯一参数并返回一个Promise,但只要有一个Promise被解决返回的Promise就被解决,无须等到所有Promise都被完成,例如:
let p1 = Promise.resolve(34)
let p2 = new Promise(function (resolve, reject) {
resolve(35)
})
let p3 = new Promise(function (resolve, reject) {
resolve(36)
})
let p4 = Promise.race([p1, p2, p3])
p4.then(function (value) {
console.log(value) // 34
})
传给Promise.race()
方法的Promise会进行竞选,以决出哪一个先被解决,如果先解决的是已完成Promise,则返回已完成Promise;如果先解决的是已拒绝Promise,则返回已拒绝Promise。例如:
let p1 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(42)
}, 0)
})
let p2 = Promise.reject(43)
let p3 = new Promise(function (resolve, reject) {
resolve(44)
})
let p4 = Promise.race([p1, p2, p3])
p4.catch(function (value) {
console.log(value) // 43
})