Promise本意是承諾.主要目的是為了解決在需要多個非同步操作的時候.產生的回撥巢狀.在es6沒出來前.用bluebird來實現.與java中的Q模組類似.
Promise物件例項建立的過程中有三種狀態, Pending、Fulfilled、Rejected. Fulfilled與Rejected間不能相互轉換.
promise的使用與原理實現
then
promise.then用於鏈式呼叫,每次執行時都會返回一個新的promise物件
all
接收一個promise陣列,如果狀態都為resolve則返回Promise的resolve狀態,如果某個promise狀態為reject則返回Promise的reject狀態
race
接收一個promise陣列, 比誰跑的快.返回第一完成的Promise狀態
promise功能的簡單實現
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
function Promise(executor) {
let self = this
// 初始化
self.status = PENDING
// 定義回撥
self.onResolvedCallbacks = []
self.onRejectedCallbacks = []
function resolve(value) {
if (value != null && value.then && typeof value.then === 'function') {
return value.then(resolve, reject)
}
// 如果是初始狀態.則改變成成功狀態
setTimeout(() => {
if (self.status === PENDING) {
self.status = FULFILLED
self.value = value
// 呼叫所有的成功
self.onResolvedCallbacks.forEach(cb => cb(self.value))
}
})
}
function reject(reason) {
setTimeout(() => {
if (self.status === PENDING) {
self.status = REJECTED
self.value = reason
self.onRejectedCallbacks.forEach(cb => cb(self.value))
}
})
}
try {
// 捕獲函式執行時出現的異常
executor(resolve, reject)
} catch(e) {
reject(e)
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('迴圈引用'))
}
let called = false
if (x instanceof Promise) {
if (x.status === PENDING) {
x.then(function(y){
resolvePromise(promise2, y, resolve, reject)
}, reject)
} else {
x.then(resolve, reject)
}
} else if(x != null && ((typeof x === 'object') || (typeof x.then === 'function'))) {
// 相容性處理
consoole.log('相容性處理')
try {
let then = x.then
if (typeof then === 'function') {
then.call(x, (y) => {
if (called) return
called = true
resolvePromise(promise2, y, resolve, reject)
}, (err) => {
if (called) return
called = true
reject(err)
})
} else {
resolve(x)
}
} catch(e) {
if (called) return
called = true
reject(e)
}
} else {
// x是一個普通的值
resolve(x)
}
}
Promise.prototype.then = function(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function(value) {return value}
onRejected = typeof onRejected === 'function' ? onRejected : function(reason) {throw reason}
let self = this
let promise2
if (self.status == FULFILLED) {
return promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
try {
let x = onFulfilled(self.value);
//如果獲取到了返回值x,會走解析Promise的過程
resolvePromise(promise2, x, resolve, reject);
} catch(e) {
//如果執行成功的回撥過程中出錯了,用錯誤原因把Promise2 reject
reject(e);
}
})
})
}
if (self.status == REJECTED) {
return promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
try {
let x = onRejected(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch(e) {
reject(e);
}
})
})
}
if(self.status == PENDING){
return promise2 = new Promise(function(resolve,reject){
self.onResolvedCallbacks.push(function(){
try{
let x =onFulfilled(self.value);
//如果獲取到了返回值x,會走解析promise的過程
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
});
self.onRejectedCallbacks.push(function(){
try{
let x =onRejected(self.value);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
});
});
}
}
Promise.prototype.catch = function(onRejected) {
this.then(null, onRejected)
}
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject)
}
})
}
Promise.deferred = Promise.defer = function(){
let defer = {};
defer.promise = new Promise((resolve,reject) => {
defer.resolve = resolve;
defer.reject = reject;
});
return defer;
}
Promise.resolve = function (value) {
return new Promise((resolve, reject) => resolve(value))
}
Promise.reject = function (reason) {
return new Promise((resolve, reject) => reject(reason))
}
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
let done = gen(promises.length, resolve)
for (let i = 0; i < promises.length; i++) {
promises[i].then(val => {
done(i, val)
}, reject)
}
})
}
function gen(i, val) {
let count = 0, result = []
return function (i, val) {
result[i] = val
if (++count === i) {
resolve(result)
}
}
}
module.exports = Promise
複製程式碼