鏍规嵁 Promise/A+ 鍜?ES6 瑙勮寖锛屽疄鐜?Promise 婧愮爜锛堥檮璇︾粏娉ㄩ噴鍜屾祴璇曪級
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了鏍规嵁 Promise/A+ 鍜?ES6 瑙勮寖锛屽疄鐜?Promise 婧愮爜锛堥檮璇︾粏娉ㄩ噴鍜屾祴璇曪級相关的知识,希望对你有一定的参考价值。
鏍囩锛?a href='http://www.mamicode.com/so/1/script' title='script'>script
rip 绀轰緥 status sap generator 浠诲姟闃熷垪 previous genPromise
promise-a-plus
const PENDING = 鈥楶ENDING鈥?const REJECTED = 鈥楻EJECTED鈥?const RESOLVED = 鈥楻ESOLVED鈥?
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
// ES6 瑙勮寖鍐欐硶 鏃犳硶閫氳繃Promise/A+娴嬭瘯
// return reject(鈥榌TypeError: Chaining cycle detected for promise #<Promise>]鈥?
// Promise/A+ 瑙勮寖鍐欐硶
return reject(new TypeError(鈥楥haining cycle detected for promise #<Promise>鈥?)
}
let called
if ((typeof x === 鈥榦bject鈥?&& x !== null) || typeof x === 鈥榝unction鈥? {
try {
const then = x.then
if (typeof then === 鈥榝unction鈥? {
then.call(x, y => {
if (called) return
called = true
resolvePromise(promise2, y, resolve, reject)
}, e => {
if (called) return
called = true
reject(e)
})
} else {
resolve(x)
}
} catch (error) {
if (called) return
called = true
reject(error)
}
} else {
resolve(x)
}
}
class Promise {
constructor(executor) {
if (typeof executor !== 鈥榝unction鈥? {
throw new TypeError(`Promise resolver ${executor} is not a function`)
}
this.status = PENDING
this.value = undefined
this.onResolvedCallbackArr = []
this.onRejectedCallbackArr = []
const resolve = (value) => {
// resolve涓娇鐢ㄦā鏉垮瓧绗︿覆锛屾棤娉曢€氳繃Promise/A+娴嬭瘯
// console.log(`${value}`)
if (value === this) {
return reject(new TypeError(鈥楥haining cycle detected for promise #<Promise>鈥?)
}
if (value instanceof Promise) {
return value.then(resolve, reject)
}
// resolve瑙f瀽thenable瀵硅薄鏄疎S6鐨勫姛鑳斤紝鏃犳硶閫氳繃Promise/A+娴嬭瘯
// if (((typeof value === 鈥榦bject鈥?&& value !== null) || typeof value === 鈥榝unction鈥? &&
// typeof value.then === 鈥榝unction鈥? {
// return process.nextTick(() => {
// try {
// value.then(resolve, reject)
// } catch (error) {
// reject(error)
// }
// })
// }
if (this.status === PENDING) {
this.value = value
this.status = RESOLVED
this.onResolvedCallbackArr.forEach(cb => cb())
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.value = reason
this.status = REJECTED
this.onRejectedCallbackArr.forEach(cb => cb())
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onResolved, onRejected) {
onResolved = typeof onResolved === 鈥榝unction鈥?? onResolved : value => value
onRejected = typeof onRejected === 鈥榝unction鈥?? onRejected : error => { throw error }
const promise2 = new Promise((resolve, reject) => {
if (this.status === RESOLVED) {
setTimeout(() => {
try {
const x = onResolved(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
}
if (this.status === PENDING) {
this.onResolvedCallbackArr.push(() => {
setTimeout(() => {
try {
const x = onResolved(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
})
this.onRejectedCallbackArr.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
})
}
})
return promise2
}
//==============浠ヤ笅闈?Promise/A+ 瑙勮寖涓殑鍐呭==================
catch(onRejected) {
return this.then(null, onRejected)
}
finally(callback) {
return this.then(value => {
return Promise.resolve(callback()).then(() => value)
}, error => {
return Promise.resolve(callback()).then(() => { throw error })
})
}
static resolve(value) {
if (value instanceof Promise) return value
return new Promise((resolve, reject) => {
if (((typeof value === 鈥榦bject鈥?&& value !== null) || typeof value === 鈥榝unction鈥? &&
typeof value.then === 鈥榝unction鈥? {
process.nextTick(() => {
try {
value.then(resolve, reject)
} catch (error) {
reject(error)
}
})
} else {
resolve(value)
}
})
}
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
static all(promises) {
return new Promise((resolve, reject) => {
if (promises == undefined || !promises[Symbol.iterator]) {
const preReason = promises === undefined ? `${promises}` : `${typeof promises} ${promises}`
return reject(new TypeError(`${preReason} is not iterable (cannot read property Symbol(Symbol.iterator))`))
}
if (promises.length === 0) return resolve([])
let index = 0
const resultArr = []
const processValue = (i, value) => {
resultArr[i] = value
if (++index === promises.length) {
return resolve(resultArr)
}
}
for (let i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then(value => {
processValue(i, value)
}, error => {
return reject(error)
})
}
})
}
static race(promises) {
return new Promise((resolve, reject) => {
if (promises == undefined || !promises[Symbol.iterator]) {
const preReason = promises === undefined ? `${promises}` : `${typeof promises} ${promises}`
return reject(new TypeError(`${preReason} is not iterable (cannot read property Symbol(Symbol.iterator))`))
}
if (promises.length === 0) return
for (let i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then(value => {
return resolve(value)
}, error => {
return reject(error)
})
}
})
}
}
Promise.defer = Promise.deferred = function () {
const dfd = {}
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve
dfd.reject = reject
})
return dfd
}
module.exports = Promise
promise-es6
/**
* ES6瀹炵幇鐨凱romise锛屽湪Promise/A+鍩虹涓婃墿灞曚簡寰堝鍔熻兘锛屾棤娉曢€氳繃涓篜romise/A+鍐欑殑娴嬭瘯
*/
const PENDING = 鈥楶ENDING鈥?const REJECTED = 鈥楻EJECTED鈥?const RESOLVED = 鈥楻ESOLVED鈥?
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
// ES6 瑙勮寖鍐欐硶 鏃犳硶閫氳繃Promise/A+娴嬭瘯
return reject(鈥榌TypeError: Chaining cycle detected for promise #<Promise>]鈥?
}
let called
if ((typeof x === 鈥榦bject鈥?&& x !== null) || typeof x === 鈥榝unction鈥? {
try {
const then = x.then
if (typeof then === 鈥榝unction鈥? {
// then.call(x, y => {
// if (called) return
// called = true
// resolvePromise(promise2, y, resolve, reject)
// }, e => {
// if (called) return
// called = true
// reject(e)
// })
// 妯℃嫙ES6鐨勮涓?寮傛璋冪敤thenable鐨則hen鏂规硶)銆傛棤娉曢€氳繃Promise/A+娴嬭瘯
process.nextTick(() => {
then.call(x, y => {
if (called) return
called = true
resolvePromise(promise2, y, resolve, reject)
}, e => {
if (called) return
called = true
reject(e)
})
})
} else {
resolve(x)
}
} catch (error) {
if (called) return
called = true
reject(error)
}
} else {
resolve(x)
}
}
class Promise {
constructor(executor) {
if (typeof executor !== 鈥榝unction鈥? {
throw new TypeError(`Promise resolver ${executor} is not a function`)
}
this.status = PENDING
this.value = undefined
this.onResolvedCallbackArr = []
this.onRejectedCallbackArr = []
const resolve = (value) => {
if (value === this) {
return reject(new TypeError(鈥楥haining cycle detected for promise #<Promise>鈥?)
}
if (value instanceof Promise) {
return value.then(resolve, reject)
}
// resolve瑙f瀽thenable瀵硅薄鏄疎S6 Promise鐨勫姛鑳斤紝鏃犳硶閫氳繃Promise/A+娴嬭瘯
if (((typeof value === 鈥榦bject鈥?&& value !== null) || typeof value === 鈥榝unction鈥? &&
typeof value.then === 鈥榝unction鈥? {
return process.nextTick(() => {
try {
value.then(resolve, reject)
} catch (error) {
reject(error)
}
})
}
if (this.status === PENDING) {
this.value = value
this.status = RESOLVED
this.onResolvedCallbackArr.forEach(cb => cb())
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.value = reason
this.status = REJECTED
this.onRejectedCallbackArr.forEach(cb => cb())
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onResolved, onRejected) {
onResolved = typeof onResolved === 鈥榝unction鈥?? onResolved : value => value
onRejected = typeof onRejected === 鈥榝unction鈥?? onRejected : error => { throw error }
const promise2 = new Promise((resolve, reject) => {
if (this.status === RESOLVED) {
process.nextTick(() => {
try {
const x = onResolved(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
})
}
if (this.status === REJECTED) {
process.nextTick(() => {
try {
const x = onRejected(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
})
}
if (this.status === PENDING) {
this.onResolvedCallbackArr.push(() => {
process.nextTick(() => {
try {
const x = onResolved(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
})
})
this.onRejectedCallbackArr.push(() => {
process.nextTick(() => {
try {
const x = onRejected(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
})
})
}
})
return promise2
}
//==============浠ヤ笅闈?Promise/A+ 瑙勮寖涓殑鍐呭==================
catch(onRejected) {
return this.then(null, onRejected)
}
finally(callback) {
return this.then(value => {
return Promise.resolve(callback()).then(() => value)
}, error => {
return Promise.resolve(callback()).then(() => { throw error })
})
}
static resolve(value) {
if (value instanceof Promise) return value
return new Promise((resolve, reject) => {
if (((typeof value === 鈥榦bject鈥?&& value !== null) || typeof value === 鈥榝unction鈥? &&
typeof value.then === 鈥榝unction鈥? {
process.nextTick(() => {
try {
value.then(resolve, reject)
} catch (error) {
reject(error)
}
})
} else {
resolve(value)
}
})
}
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
static all(promises) {
return new Promise((resolve, reject) => {
if (promises == undefined || !promises[Symbol.iterator]) {
const preReason = promises === undefined ? `${promises}` : `${typeof promises} ${promises}`
return reject(new TypeError(`${preReason} is not iterable (cannot read property Symbol(Symbol.iterator))`))
}
if (promises.length === 0) return resolve([])
let index = 0
const resultArr = []
const processValue = (i, value) => {
resultArr[i] = value
if (++index === promises.length) {
return resolve(resultArr)
}
}
for (let i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then(value => {
processValue(i, value)
}, error => {
return reject(error)
})
}
})
}
static race(promises) {
return new Promise((resolve, reject) => {
if (promises == undefined || !promises[Symbol.iterator]) {
const preReason = promises === undefined ? `${promises}` : `${typeof promises} ${promises}`
return reject(new TypeError(`${preReason} is not iterable (cannot read property Symbol(Symbol.iterator))`))
}
if (promises.length === 0) return
for (let i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then(value => {
return resolve(value)
}, error => {
return reject(error)
})
}
})
}
}
Promise.defer = Promise.deferred = function () {
const dfd = {}
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve
dfd.reject = reject
})
return dfd
}
module.exports = Promise
promise-comment
/*
Promise 瀹炵幇瑙勮寖 Promise/A+ 鍦板潃: https://promisesaplus.com/
浼樼偣锛氳В鍐冲紓姝ラ棶棰?1. 澶氫釜骞跺彂寮傛璇锋眰锛屽悓鏃惰幏鍙栫粨鏋?-> promise.all
2. 閾惧紡寮傛璇锋眰锛堟伓榄旈噾瀛楀銆佸洖璋冨湴鐙憋級-> promise.then 閾惧紡璋冪敤
缂虹偣锛?1. 鏈韩杩樻槸鍩轰簬鍥炶皟鍑芥暟鐨勫舰寮?2. 鏃犳硶涓柇寮傛澶勭悊缁撴灉
promise寰幆寮曠敤闂锛? 寰幆寮曠敤鍙兘鍙戠敓鍦ㄥ紓姝ユ儏鍐典笅(then 鐨勫弬鏁板嚱鏁颁腑 鎴?瀹氭椂鍣ㄤ腑)銆傛鏃舵瀯閫犲嚱鏁版墠鑳芥墽琛屽畬姣曡幏鍙栧埌褰撳墠promise锛岀劧鍚庡啀寮曠敤锛屽彂鐢熷惊鐜紩鐢? 杩斿洖涓€涓柊鐨刾romise閮戒細鎵ц鏋勯€犲嚱鏁帮紙璋冪敤then鐨勬椂鍊欙級
promise閫掑綊瑙f瀽闂锛? 瑙f瀽promise鍗?璋冪敤 璇romise鐨?then鏂规硶锛屽皢澶栧眰promise鐨剅esolve reject 浣滀负鍐呭眰promise杩斿洖鍚?瑙﹀彂鎵ц鐨?then鏂规硶鐨?鍥炶皟
then鐨勫弬鏁板嚱鏁拌繑鍥瀙romise浼氶€掑綊瑙f瀽锛岀洿鍒拌繑鍥為潪promise鎴栬reject銆? 搴曞眰鍘熺悊鏄皢then杩斿洖鐨?promise鐨?resolve鍜宺eject 浣滀负鍙傛暟鍑芥暟杩斿洖鐨?promise鐨?then鐨?鍥炶皟锛? 褰撳弬鏁板嚱鏁拌繑鍥炵殑 promise杩斿洖鍚?鎵嶈Е鍙戞墽琛? 鏋勯€犲嚱鏁颁腑鎻愪緵鐨剅esolve鏂规硶浼氶€掑綊瑙f瀽锛岀洿鍒拌繑鍥為潪promise鎴栬reject锛坮eject涓嶄細瑙f瀽promise锛? 搴曞眰鍘熺悊鏄皢鑷繁鍜宺eject浣滀负鍙傛暟promise鐨則hen鐨勫洖璋冿紝褰撳弬鏁皃romise杩斿洖鍚庯紝鎵嶈Е鍙戞墽琛? 鍥犳閫掑綊瑙f瀽鐨勬椂鍊? 鏌愬唴灞傚け璐ュ悗锛屽灞備緷娆¤皟鐢ㄥ叾reject鏂规硶锛屼篃閮借繑鍥炲け璐? 鏈€鍐呭眰鎴愬姛鍚庯紝澶栧眰渚濇璋冪敤鍏秗esolve鏂规硶锛屼篃閮借繑鍥炴垚鍔? 娉ㄥ唽then鍥炶皟
閫掓帹鐨勬椂鍊欎笉浼氬皢then鐨勫洖璋冩敞鍐屽埌寰换鍔¢槦鍒楀熬閮? 鍥炲綊鐨勬椂鍊欙紝promise鐘舵€佹敼鍙樻墠浼氭敞鍐屽埌寰换鍔¢槦鍒楀熬閮紝鍦ㄤ笅娆″惊鐜墽琛?
promise 寮傚父闂锛? 1. 濡傛灉娌℃湁浼犻€抏xecutor鍑芥暟锛岀洿鎺ユ姏鍑哄紓甯革紝澶栭潰鍙互鍚屾鎹曡幏
2. 濡傛灉鍦╡xecutor鍑芥暟浣撲腑寮傛浠g爜鎶涘嚭寮傚父锛屽闈㈡棤娉曞悓姝ユ崟鑾凤紝鍙兘鍏ㄥ眬鎹曡幏锛堟垨鑰呭紓姝ヤ唬鐮佽嚜宸辨崟鑾凤紝璋冪敤reject閫氱煡澶栭潰锛? 3. 鍏朵粬鎯呭喌涓媝romise涓嶄細灏嗗紓甯告姏鍒板叏灞€锛岄兘鏄繑鍥炰竴涓け璐ョ殑promise
4. 濡傛灉鍦╡xecutor鍑芥暟浣撲腑鍚屾浠g爜鎶涘嚭寮傚父
4.1 鍦╮esolve鎴杛eject涔嬪墠鎶涘嚭鐨勫紓甯革紝琚玹ry-catch鎹曡幏锛岃繑鍥炲け璐ョ殑promise
4.2 鍦╮esolve鎴杛eject鎺ユ敹鐨勫弬鏁板嚱鏁颁腑鎶涘嚭寮傚父锛岃try-catch鎹曡幏锛岃繑鍥炲け璐ョ殑promise
4.3 鍦╮esolve鎴杛eject涔嬪悗鎶涘嚭鐨勫紓甯革紝琚玹ry-catch鎹曡幏锛屼笉褰卞搷promise鐨勭姸鎬? 5. 濡傛灉鍦╰hen鍥炶皟鍑芥暟涓姏鍑哄紓甯? 5.1 琚玹hen涓殑try-catch鎹曡幏锛岃繑鍥炲け璐ョ殑promise
6. thenable瀵硅薄
6.1 濡傛灉鍦ㄥ叾then鍙傛暟鍑芥暟resolve鍜宺eject涔嬪墠鎶涘紓甯革紝閮戒細琚玹ry-catch鎹曡幏锛岃繑鍥炲け璐ョ殑promise
e.g. Promise.resolve銆佹瀯閫犲嚱鏁颁腑鐨剅esolve銆乼hen鐨剅esolvePromise
6.2 濡傛灉鍦ㄥ叾then鍙傛暟鍑芥暟resolve鍜宺eject涔嬪悗鎶涘紓甯革紝浼氳try-catch鎹曡幏锛屼絾鏄笉鏀瑰彉promise鐨勭姸鎬?
promise then浜嬩欢寰幆闂锛? 璋冪敤then灏变細灏唗hen鐨勫弬鏁板嚱鏁版敞鍐屽埌寰换鍔¢槦鍒楁湯灏撅紝鍦ㄤ笅涓€杞簨浠跺惊鐜墠浼氭墽琛岋紙寤惰繜涓€杞墽琛岋級
Promise/A+ 娴嬭瘯闂
1. 娉ㄦ帀瑙勮寖鏂规硶涓殑鏃ュ織
2. 娉ㄦ帀闈炶鑼冧腑鐨勫姛鑳斤紙3涓湴鏂癸級
*/
const u = require("../utils")
const log = u.debugGenerator(__filename)
// 鐘舵€侊紙鐢ㄥ父閲忚〃绀猴級
// 1. Promise鏈変笁涓姸鎬侊紝resolved(fulfilled) rejected pending(榛樿鍒濆鐘舵€?
// 2. 涓€鏃︽敼鍙樻棤娉曚慨鏀癸紝鍙湁pending鐘舵€佷笅鎵嶅彲浠ヤ慨鏀?const RESOLVED = 鈥楻ESOLVED鈥?const REJECTED = 鈥楻EJECTED鈥?const PENDING = 鈥楶ENDING鈥?
// 杩欎釜鏂规硶瑕佸吋瀹?鎵€鏈?鍏朵粬搴撳疄鐜扮殑promise锛屼緥濡?bluebird銆乹銆乪s6-promise銆傝繖浜涘簱鍙互鐩镐簰璋冪敤涓昏闈?resolvePromise 鏂规硶鍏煎
const resolvePromise = (promise2, x, resolve, reject) => {
// 寰幆寮曠敤-鑷繁绛夊緟鑷繁锛坧romise2 鍜?x 寮曠敤鍚屼竴涓璞★級
if (promise2 === x) {
log.debug(鈥榩romise.then circular reference鈥?
// ES6 瑙勮寖鍐欐硶 鏃犳硶閫氳繃Promise/A+娴嬭瘯
return reject(鈥榌TypeError: Chaining cycle detected for promise #<Promise>]鈥?
// Promise/A+ 瑙勮寖
// return reject(new TypeError(鈥楥haining cycle detected for promise #<Promise>鈥?)
}
let called // 鏍囪锛岄槻姝㈠埆鐨勫簱瀹炵幇鐨刾romise璧版垚鍔熷悗鍙堣蛋澶辫触
// 涓ユ牸鏍规嵁瑙勮寖鍒ゆ柇锛岀‘淇濆彲浠ュ吋瀹瑰叾浠栧簱瀹炵幇鐨刾romise
// if (x instanceof Promise) { } // 涓嶈兘鐢ㄨ繖绉嶆柟寮忓垽鏂瓁鏄笉鏄疨romise锛屽洜涓簒鍙兘鏄埆鐨勫簱瀹炵幇鐨凱romise鐨勫疄渚? if ((typeof x === 鈥榦bject鈥?&& x !== null) || typeof x === 鈥榝unction鈥? {
// 濡傛灉x鏄璞℃垨鍑芥暟
try {
// promise(x)閮芥湁涓€涓猼hen鏂规硶锛屽彇x鐨勫睘鎬hen锛岀湅鏄笉鏄嚱鏁版潵鍒ゆ柇x鏄笉鏄痯romise
// 閫氳繃 x.then 鍙栧€煎彲鑳戒細鎶ラ敊锛岄渶瑕乼ry-catch (鍙傝€冪ず渚?promise-resolvePromise.js)
const then = x.then
if (typeof then === 鈥榝unction鈥? {
// 鑷虫锛岃涓簒鏄痯romise
// 涓嶈兘鍐欐垚 x.then锛屽洜涓鸿繖鏍蜂細鍐嶆鍙栧€硷紝鏈夊彲鑳芥姤閿?(鍙傝€冪ず渚?promise-resolvePromise.js)
// 鐢?call 鏂规硶锛屼繚璇乼hen鏂规硶涓殑THIS鏄渶瑕佽幏鍙栫粨鏋滅殑promise瀹炰緥(x)銆傚鏋滀笉call鍒欐槸window鎴杇lobal
// 濡傛灉鏄痶henable瀵硅薄锛宼hen 鏂规硶浣撲腑鍙兘浼氭姤閿欙紝浼氳catch鎹曡幏鍒? // 鏍规嵁鍐呭眰promise(x)鐨勭姸鎬佸拰鍊?鍐冲畾澶栧眰promise2鐨勭姸鎬佸拰鍊?
// then.call(x,
// y => {
// //銆愯繖閲岃皟鐢ㄥ埆浜哄疄鐜扮殑promise涓殑then鏂规硶锛屾墽琛岃嚜宸变紶鍏ョ殑鍥炶皟銆? // // 鏃犳硶鎺у埗鍒汉鐨勪唬鐮佹墽琛屽嚑涓洖璋冿紝鍙兘鎺у埗鑷繁浼犲叆鐨勫洖璋冿紙娣诲姞鍒ゆ柇锛夐槻姝㈣蛋鎴愬姛鍚庡張璧板け璐? // if (called) return
// called = true
// // 绛?x(promise) 杩斿洖鎴愬姛锛堝€间负y锛夈€傚垯鎵цx鐨則hen鏂规硶鐨勭涓€涓弬鏁板嚱鏁帮紙杩欓噷浼犲叆鐨勫洖璋冿級
// // 鍗虫墽琛屽綋鍓峵hen鏂规硶杩斿洖promise2鐨剅esolve鏂规硶锛屼娇褰撳墠then杩斿洖涓€涓垚鍔熺殑promise2锛屽€间负x(promise)鐨勬垚鍔熺粨鏋測
// // resolve(y) 浣嗘槸涓轰簡瑙e喅杩斿洖promise(x)鎴愬姛鍙堣繑鍥瀙romise鐨勭幇璞?y杩樻槸涓€涓猵romise)锛岃繖閲岄渶瑕侀€掑綊瑙f瀽
// log.debug(`before resolvePromise recursion, y is 鈥?{y}鈥榒)
// // 绗竴涓弬鏁颁粛鐒舵槸鏈€澶栧眰then杩斿洖鐨刾romise2锛堢敤鏉ヤ繚璇佷笉鍙戠敓寰幆寮曠敤锛?resolve銆乺eject 涔熸槸promise2鐨? // // 褰搚(promise)杩斿洖鍚庯紝璋冪敤promise2鐨剅esolve鎴杛eject
// // 褰撴渶缁坹涓嶆槸promise,鍦ㄣ€愬嚭鍙?鎴?銆戠粨鏉燂紝鎴杫杩斿洖澶辫触锛屽洖褰掑埌杩欓噷锛屽祵濂楃殑resolvePromise渚濇缁撴潫
// resolvePromise(promise2, y, resolve, reject)
// log.debug(`end resolvePromise recursion, y is 鈥?{y}鈥榒)
// },
// e => {
// // 闃叉璧版垚鍔熷悗鍙堣蛋澶辫触
// if (called) return
// called = true
// // 鍚岀悊锛屽鏋?x(promise) 杩斿洖澶辫触锛屽垯褰撳墠then杩斿洖鐨刾romise2杩斿洖澶辫触锛屽€间负x(promise)鐨勫け璐ュ師鍥? // // promise(x)澶辫触鍙堣繑鍥瀙romise锛堝嵆e鏄竴涓猵romise锛夛紝涓嶅啀閫掑綊瑙f瀽锛岀洿鎺ュ皢鏈€鍚庣殑promise浣滀负澶辫触鍘熷洜杩斿洖
// reject(e)
// })
// 鏍规嵁娴嬭瘯缁撴灉锛?.promise-then.js 鏈€鍚庝竴涓祴璇曠敤渚嬶級锛岄渶瑕佸紓姝ユ墽琛宼henable鐨則hen鏂规硶銆備娇鐢?process.nextTick锛堜釜浜虹悊瑙o級
// 1. process.nextTick 浜嬩欢灏嗗湪褰撳墠闃舵鐨勫熬閮ㄦ墽琛岋紙涓嬫浜嬩欢寰幆涔嬪墠锛? // 2. process.nextTick 灏嗕簨浠剁淮鎶ゅ湪 nextTickQueue 涓? // 瀵逛簬promise鏉ヨ锛屾病鍔犱箣鍓嶏紝绔嬪嵆璋冪敤then灏嗗洖璋冩斁鍏?nextTickQueue 涓紱鍔犱簡涔嬪悗锛屽厛灏嗗then鐨勮皟鐢ㄦ斁鍏?nextTickQueue 涓? // 鎵ц浼氬悗锛屽啀灏嗗洖璋冩斁鍏?nextTickQueue 涓€傚嵆瀵逛簬nextTickQueue鏉ヨ锛屽洖璋冧細寤惰繜鎵ц锛屼絾鏈€缁堥兘鍦ㄥ綋鍓嶉樁娈垫墽琛岋紝
// 瀵逛簨浠跺惊鐜暣浣撴潵璇存病鏈夊お澶х殑褰卞搷
// 3. 鏃犳硶閫氳繃Promise/A+ 娴嬭瘯锛侊紒锛?
process.nextTick(() => {
then.call(x,
y => {
//銆愯繖閲岃皟鐢ㄥ埆浜哄疄鐜扮殑promise涓殑then鏂规硶锛屾墽琛岃嚜宸变紶鍏ョ殑鍥炶皟銆? // 鏃犳硶鎺у埗鍒汉鐨勪唬鐮佹墽琛屽嚑涓洖璋冿紝鍙兘鎺у埗鑷繁浼犲叆鐨勫洖璋冿紙娣诲姞鍒ゆ柇锛夐槻姝㈣蛋鎴愬姛鍚庡張璧板け璐? if (called) return
called = true
// 绛?x(promise) 杩斿洖鎴愬姛锛堝€间负y锛夈€傚垯鎵цx鐨則hen鏂规硶鐨勭涓€涓弬鏁板嚱鏁帮紙杩欓噷浼犲叆鐨勫洖璋冿級
// 鍗虫墽琛屽綋鍓峵hen鏂规硶杩斿洖promise2鐨剅esolve鏂规硶锛屼娇褰撳墠then杩斿洖涓€涓垚鍔熺殑promise2锛屽€间负x(promise)鐨勬垚鍔熺粨鏋測
// resolve(y) 浣嗘槸涓轰簡瑙e喅杩斿洖promise(x)鎴愬姛鍙堣繑鍥瀙romise鐨勭幇璞?y杩樻槸涓€涓猵romise)锛岃繖閲岄渶瑕侀€掑綊瑙f瀽
log.debug(`before resolvePromise recursion, y is 鈥?{y}鈥榒)
// 绗竴涓弬鏁颁粛鐒舵槸鏈€澶栧眰then杩斿洖鐨刾romise2锛堢敤鏉ヤ繚璇佷笉鍙戠敓寰幆寮曠敤锛?resolve銆乺eject 涔熸槸promise2鐨? // 褰搚(promise)杩斿洖鍚庯紝璋冪敤promise2鐨剅esolve鎴杛eject
// 褰撴渶缁坹涓嶆槸promise,鍦ㄣ€愬嚭鍙?鎴?銆戠粨鏉燂紝鎴杫杩斿洖澶辫触锛屽洖褰掑埌杩欓噷锛屽祵濂楃殑resolvePromise渚濇缁撴潫
resolvePromise(promise2, y, resolve, reject)
log.debug(`end resolvePromise recursion, y is 鈥?{y}鈥榒)
},
e => {
// 闃叉璧版垚鍔熷悗鍙堣蛋澶辫触
if (called) return
called = true
// 鍚岀悊锛屽鏋?x(promise) 杩斿洖澶辫触锛屽垯褰撳墠then杩斿洖鐨刾romise2杩斿洖澶辫触锛屽€间负x(promise)鐨勫け璐ュ師鍥? // promise(x)澶辫触鍙堣繑鍥瀙romise锛堝嵆e鏄竴涓猵romise锛夛紝涓嶅啀閫掑綊瑙f瀽锛岀洿鎺ュ皢鏈€鍚庣殑promise浣滀负澶辫触鍘熷洜杩斿洖
reject(e)
})
})
} else {
// x 涓嶆槸 promise锛堟槸涓櫘閫氬璞℃垨鏅€氬嚱鏁帮級锛屼緥濡傦細{then:123}
// 閫掑綊鍑哄彛1銆愮粓缁撹€?銆? log.debug(`the property 鈥榯hen鈥?of 鈥榵鈥?is not a function, x is 鈥?{x}鈥榒)
resolve(x)
}
} catch (error) {
// x.then 鍙栧€煎嚭閿? // thenable 鏂规硶浣撲腑锛屾墽琛屼簡浼犲叆鐨?resolve 鍙傛暟鍑芥暟鍚庯紝鍐嶆姏寮傚父锛屼篃浼氳繘鍏ヨ繖閲? log.error(`thenable error 鈥?{error}鈥榒)
// 闃叉璧版垚鍔熷悗鍙堣蛋澶辫触
if (called) return
called = true
reject(error)
}
} else {
// 濡傛灉x涓嶆槸瀵硅薄鎴栧嚱鏁帮紝鐩存帴杩斿洖鎴愬姛鐘舵€佺殑promise2
// 閫掑綊鍑哄彛2銆愮粓缁撹€?銆? log.debug(`x is not a promise, x is ${x}`)
resolve(x)
}
}
log.debug(鈥?===== my promise ======鈥?
class Promise {
// 1. 鍒涘缓绫荤殑瀹炰緥锛岄渶瑕佺瓑鏋勯€犲嚱鏁颁腑鐨勪唬鐮佸叏閮ㄦ墽琛屽畬姣曪紝鎵嶈兘鎷垮埌鍊? // 1.1 濡傛灉resolve鎴杛eject鏄紓姝ヨ皟鐢紝鍒欐瀯閫犲嚱鏁版墽琛屽畬姣曡繑鍥?PENDING 鐘舵€佺殑promise
// 2. THIS
// 2.1 鏋勯€犲嚱鏁颁腑鐨凾HIS鎸囦唬褰撳墠瀹炰緥瀵硅薄
constructor(executor) {
// executor 鎵ц鍣? // 1. 鏋勯€犲嚱鏁板繀椤讳紶鍏ヤ竴涓弬鏁帮紝绫诲瀷鏄嚱鏁? // 2. 濡傛灉涓嶆槸鍑芥暟锛屽垯鐩存帴鎶涚被鍨嬮敊璇?
if (typeof executor !== "function") {
throw new TypeError(`Promise resolver ${executor} is not a function`)
}
this.status = PENDING // 鐘舵€侊細鍒濆鐘舵€佷负 pending
this.value = undefined // 鍊? 淇濆瓨鎴愬姛鐨勭粨鏋滄垨澶辫触鐨勫師鍥?
this.onResolvedCallbacks = [] // 瀛樻斁鐘舵€佸彉涓烘垚鍔熸椂鐨勫洖璋? this.onRejectedCallbacks = [] // 瀛樻斁鐘舵€佸彉涓哄け璐ユ椂鐨勫洖璋?
// 1. 璋冪敤 resolve 鏂规硶
// 1.1 濡傛灉value鏄痯romise锛屽垯寮傛锛堣皟鐢級鎵ц锛屼綔涓?promise 鎴愬姛鍚巘hen鐨勬垚鍔熷洖璋冩墽琛? // 1.2 濡傛灉value闈瀙romise锛屽垯鍚屾锛堣皟鐢級鎵ц锛屽皢value璧嬪€肩粰THIS锛堝鏋滄斁鍒板畾鏃跺櫒涓紝灞炰簬寮傛璋冪敤锛屼絾鏄皟鐢ㄥ悗鏄珛鍗冲悓姝ユ墽琛岀殑锛? // 2. THIS
// 2.1 璋冪敤 resolve 鏂规硶鐨勬椂鍊欐病鏈夋寚鏄庤皝璋冪敤鐨勶紝鍥犳杩欓噷鐨凾HIS闇€瑕佹槑纭寚鍚戝綋鍓嶅疄渚嬶紙浣跨敤绠ご鍑芥暟,THIS鏄瀯閫犲嚱鏁颁腑鐨凾HIS锛? const resolve = (value) => {
// resolve涓娇鐢ㄦā鏉垮瓧绗︿覆锛屾棤娉曢€氳繃Promise/A+娴嬭瘯
log.debug(`call resolve, status is 鈥?{this.status}鈥? value is 鈥?{value}鈥榒)
// 寮傛resolve(鈥榯his鈥?锛屼細瀵艰嚧寰幆寮曠敤-鑷繁绛夊緟鑷繁
if (value === this) {
// 杩斿洖涓€涓け璐ョ殑promise
return reject(new TypeError(鈥楥haining cycle detected for promise #<Promise>鈥?)
}
// 杩欓噷涓嶇敤鍏煎鍏朵粬鐗堟湰鐨刾romise锛屽彧鏄嚜宸辩殑鍔熻兘锛堥潪瑙勮寖涓殑锛? if (value instanceof Promise) {
// 閫掑綊瑙f瀽promise锛岀洿鍒皏alue闈瀙romise
// 鏄紓姝ユ墽琛岋紙娑夊強鍒皌hen锛? // 璋冪敤鍐呴儴then鏂规硶锛屼笉浼氭姏鍑哄紓甯? return value.then(resolve, reject)
}
// resolve瑙f瀽thenable瀵硅薄鏄疎S6鐨勫姛鑳斤紝鏃犳硶閫氳繃Promise/A+娴嬭瘯
if (((typeof value === 鈥榦bject鈥?&& value !== null) || typeof value === 鈥榝unction鈥? &&
typeof value.then === 鈥榝unction鈥? {
// thenable 瀵硅薄
// 璋冪敤鍐呴儴then鏂规硶锛屽叾鍥炶皟鏄紓姝ユ墽琛岀殑锛岃€岃皟鐢╰henable瀵硅薄涓璽hen鏂规硶锛屽叾鍥炶皟鏄悓姝ョ殑(璋冪敤thenable.then灏变細鎵ц)
// 鍥犳杩欓噷闇€瑕佸湪璋冪敤鐨勬椂鍊欏紓姝ワ紙寰换鍔★級
// 璋冪敤鍐呴儴鐨則hen鏂规硶锛屾棤娉曞仛鎵嬭剼銆傝€宼henable瀵硅薄涓彲浠ュthen鏂规硶鍋氭墜鑴氾紝鍥犳杩欓噷瑕佹斁鍒皌ry-catch涓? return process.nextTick(() => {
try {
value.then(resolve, reject)
} catch (error) {
reject(error)
}
})
}
// 鍙湁 pending 鐘舵€佸彲浠ヤ慨鏀圭姸鎬佸拰鍊硷紙纭繚resolve鍜宺eject鍙細鎵ц涓€娆★級
if (this.status === PENDING) {
this.value = value
this.status = RESOLVED
this.onResolvedCallbacks.forEach(cb => cb())
}
// JSON.stringify() 涓㈠け娉ㄥ唽鐨勫嚱鏁? log.debug("------promise is------", this) // 鎵撳嵃resolve鎵€灞炵殑promise
}
// 1. 璋冪敤 reject鏂规硶锛屽悓姝ユ墽琛岋紙濡傛灉鏀惧埌瀹氭椂鍣ㄤ腑锛屽睘浜庡紓姝ヨ皟鐢紝浣嗘槸璋冪敤鍚庢槸绔嬪嵆鍚屾鎵ц鐨勶級
// 1.1 涓嶇reason灞炰簬浠€涔堢被鍨嬪€硷紝閮藉師鏍疯祴鍊肩粰THIS
// 1.2 濡傛灉reason鏄痯romise锛宺eject涓嶄細杩涜瑙f瀽锛岀洿鎺ヨ祴鍊肩粰THIS
const reject = (reason) => {
log.debug(`call reject, status is 鈥?{this.status}鈥? reason is 鈥?{reason}鈥榒)
// 鍙湁 pending 鐘舵€佸彲浠ヤ慨鏀圭姸鎬佸拰鍊硷紙纭繚resolve鍜宺eject鍙細鎵ц涓€娆★級
if (this.status === PENDING) {
this.value = reason
this.status = REJECTED
this.onRejectedCallbacks.forEach(cb => cb())
}
}
// 1. executor鍑芥暟锛岀珛鍗冲悓姝ユ墽琛? // 1.1 鍚屾浠g爜鎶ラ敊锛屽彲浠ユ崟鑾峰埌寮傚父
// 1.2 寮傛浠g爜鎶ラ敊锛屾棤娉曟崟鑾凤紙褰撳紓姝ヤ唬鐮佹墽琛岀殑鏃跺€欙紝鎹曡幏寮傚父鐨勫嚱鏁板凡缁忓嚭鏍堜簡锛? // 2. executor 涓粯璁ゆ彁渚?resolve reject 鏂规硶
// 2.1 璋冪敤 resolve 灏嗙姸鎬佸彉涓?resolved锛屽€间负鎴愬姛缁撴灉銆傝Е鍙憈hen鐨勬垚鍔熷洖璋冩墽琛? // 2.2 璋冪敤 reject 灏嗙姸鎬佸彉涓?rejected锛屽€间负澶辫触鍘熷洜銆傝Е鍙憈hen鐨勫け璐ュ洖璋冩墽琛? // 2.3 涓嶆槸闈欐€佹柟娉曪紝涓嶆槸瀹炰緥鏂规硶锛屼篃涓嶆槸绉佹湁鏂规硶锛屽氨鏄竴涓湪鏋勯€犲嚱鏁颁腑瀹氫箟鐨勬柟娉? // 2.4 鏄竴涓棴鍖呭嚱鏁帮紝鍦ㄦ瀯閫犲嚱鏁颁腑瀹氫箟锛屽湪鍒涘缓promise鐨勫湴鏂规墽琛?
// 2.5 璋冪敤 resolve鎴杛eject 涓嶄細缁撴潫executor鍑芥暟鐨勬墽琛岋紝鍗冲悗闈㈢殑浠g爜渚濈劧浼氭墽琛屻€? // 涓€鑸涓猴紝璋冪敤 resolve鎴杛eject鍚庯紝promise鐨勪綔鐢ㄥ氨瀹屾垚浜嗭紝鍚庣画鎿嶄綔搴旇鏀惧埌then鏂规硶涓紝
// 鍥犳涓€鑸湪璋冪敤 resolve鎴杛eject鍓嶅姞涓妑eturn
// 2.6 resolve 鍜?reject 鐨勫弬鏁板彧鑳芥槸鍊肩被鍨嬶紝濡傛灉鏄釜琛ㄨ揪寮忥紙new鏋勯€犲嚱鏁?鎴?鏅€氬嚱鏁癧璋冪敤]锛夛紝
// 浼氬厛灏嗗叾鍦╡xecutor鍑芥暟浣撲腑鎵ц锛屽緱鍒拌〃杈惧紡鐨勮繑鍥炲€煎啀浼犵粰 resolve 鎴?reject 鎵ц
// 濡傛灉鍦ㄦ墽琛岃繃绋嬩腑鎶ラ敊锛屽彲浠ヨexecutor鐨則ry-catch鎹曡幏
// 3. 鑷畾涔? // 3.1 鎴愬姛杩樻槸澶辫触锛堜粈涔堟儏鍐典笅璋冪敤 resolve/reject锛夌敱鐢ㄦ埛鍐冲畾
// 3.2 鎴愬姛鐨勭粨鏋滃拰澶辫触鐨勫師鍥狅紝鐢辩敤鎴峰喅瀹? try {
executor(resolve, reject)
} catch (error) {
log.error(`catch executor error: 鈥?{error}鈥榒)
reject(error)
}
}
// then
// 1. Promise 蹇呴』鍏锋湁then鏂规硶
// 1.1 then鏂规硶闇€瑕佺敤鎴蜂紶鍏ヤ袱涓弬鏁板嚱鏁帮紙鍥炶皟鍑芥暟锛夛紝绗竴涓槸鐘舵€佸彉涓烘垚鍔熸椂瑙﹀彂鎵ц(鎺ユ敹鎴愬姛鐨勭粨鏋?銆愭垚鍔熷洖璋冦€戯紝
// 绗簩涓槸鐘舵€佸彉涓哄け璐ユ椂瑙﹀彂鎵ц锛堟帴鏀跺け璐ョ殑鍘熷洜锛夈€愬け璐ュ洖璋冦€戙€傘€愪袱涓弬鏁板嚱鏁板彧鑳借Е鍙戞墽琛屼竴涓€? // 1.2 濡傛灉鏌愪釜鍙傛暟鍑芥暟娌℃湁浼犻€掞紝鍒欎細浣跨敤榛樿鍙傛暟鍑芥暟
// 1.3 then鏂规硶鍚屾鎵ц锛屼絾鏄紶鍏ョ殑涓や釜鍙傛暟鍑芥暟锛堝洖璋冿級鏄紓姝ユ墽琛? // ES6鐨凱romise涓璽hen灞炰簬寰换鍔★紝鍏朵粬Promise搴撳彲鑳芥槸瀹忎换鍔★紙bluebird锛? // 鏃犳硶鑷繁瀹炵幇涓€涓井浠诲姟锛屽彧鑳借皟鐢ㄥ涓荤幆澧冩彁渚涚殑API
// 1.4 then鏂规硶鍦ㄨ皟鐢ㄥ弬鏁板嚱鏁版椂浼氫紶鍏モ€楾HIS鈥?璋冪敤then鐨刾romise瀹炰緥)鐨勫€硷紝鍗冲弬鏁板嚱鏁板彲浠ユ嬁鍒板綋鍓峱romise鐨勫€? // 2. then鏂规硶 杩斿洖涓€涓€愭柊銆戠殑promise
// 2.1 then 鏂规硶鐨勬墽琛岃繃绋嬬被浼兼墽琛屾瀯閫犲嚱鏁帮紝澶勭悊瀹屽洖璋冨嚱鏁帮紙娉ㄥ唽鍒板井浠诲姟闃熷垪鎴栨坊鍔犲埌寰呮墽琛岄槦鍒楋級涔嬪悗锛岀珛鍗宠繑鍥?PENDING 鐘舵€佺殑promise
// 缁х画鎵ц鍚庣画鍚屾浠g爜锛堝洜姝ら摼寮忚皟鐢ㄤ細鍚屾鎵цthen鏂规硶锛屽畬鍚庡啀鎵цthen鏂规硶鐨勫洖璋冿級
// 3. then鏂规硶 杩斿洖promise鐨勭姸鎬?鍙?閾惧紡璋冪敤 promise杩斿洖鍊肩殑浼犻€掕鍒欙細
// 3.1 闇€瑕佸湪鍙傛暟鍑芥暟涓敤return鏄庣‘鎸囧畾杩斿洖鍊硷紝鍚﹀垯then鏂规硶榛樿杩斿洖涓€涓垚鍔熺殑promise锛屽€兼槸undefined锛屼紶鍏ヤ笅涓€涓猼hen鐨勬垚鍔熷洖璋冧腑
// 3.2 濡傛灉鍙傛暟鍑芥暟杩斿洖鐨勬槸銆愭櫘閫氬€笺€戯紙闈瀙romise瀹炰緥銆乼henable瀵硅薄銆佸紓甯革紝鍗虫櫘閫氬璞°€佹暟瀛椼€佸瓧绗︿覆銆乽ndefined锛堥粯璁わ級锛? // 鍒檛hen鏂规硶杩斿洖涓€涓垚鍔熺殑promise锛屽€兼槸璇ユ櫘閫氬€硷紝浼犲叆涓嬩竴涓猼hen鐨勬垚鍔熷洖璋冧腑
// 3.3 濡傛灉鍙傛暟鍑芥暟銆愭姏鍑哄紓甯搞€戯紝浼氳then鍐呴儴鐨則ry-catch鎹曡幏
// 鍒檛hen鏂规硶杩斿洖涓€涓け璐ョ殑promise锛屽€兼槸寮傚父鍘熷洜锛屼紶鍏ヤ笅涓€涓猼hen鐨勫け璐ュ洖璋冧腑
// 3.4 濡傛灉鍙傛暟鍑芥暟杩斿洖涓€涓€恜romise瀹炰緥銆戯紝鍒欒promise瀹炰緥鐨勭姸鎬佷細鍐冲畾褰撳墠then鏂规硶杩斿洖promise鐨勭姸鎬侊紝浠庤€屽喅瀹氫笅涓€涓猼hen鍙傛暟鍑芥暟鐨勬墽琛屾儏鍐? // 3.4.1 濡傛灉鍙傛暟鍑芥暟杩斿洖涓€涓垚鍔熺殑promise锛屽垯褰撳墠then涔熻繑鍥炰竴涓垚鍔熺殑promise锛屽€兼槸鍙傛暟鍑芥暟杩斿洖promise鐨勬垚鍔熺粨鏋滐紝浼犲叆涓嬩竴涓猼hen鐨勬垚鍔熷洖璋冧腑
// 3.4.2 濡傛灉鍙傛暟鍑芥暟杩斿洖涓€涓け璐ョ殑promise锛屽垯褰撳墠then涔熻繑鍥炰竴涓け璐ョ殑promise锛屽€兼槸鍙傛暟鍑芥暟杩斿洖promise鐨勫け璐ュ師鍥狅紝浼犲叆涓嬩竴涓猼hen鐨勫け璐ュ洖璋冧腑
// 4. 閿欒澶勭悊
// 4.1 濡傛灉璺濈鑷繁鏈€杩戠殑then娌℃湁浼犻€掔浜屼釜鍙傛暟鍑芥暟锛屽垯鎵句笅涓€涓猼hen鎴朿atch
// 5. THIS
// 5.1 then鏂规硶涓殑THIS鏄皟鐢╰hen鐨刾romise瀹炰緥
then(onResolved, onRejected) {
// 鏂规硶涓殑THIS鏄皟鐢╰hen鐨刾romise瀹炰緥
log.info(`call then, promise status is ${this.status}`)
// 鍒ゆ柇鏄惁浼犻€掑弬鏁颁互鍙婁紶閫掔殑鏄笉鏄嚱鏁? // onResolved = typeof onResolved === 鈥榝unction鈥?? onResolved : value => { return value }
onResolved = typeof onResolved === 鈥榝unction鈥?? onResolved : v => v
// onRejected = typeof onRejected === 鈥榝unction鈥?? onRejected : err => { throw err }
onRejected = typeof onRejected === 鈥榝unction鈥?? onRejected : e => { throw e }
// 鎳掗€掑綊锛屾瘡娆¤皟鐢ㄥ氨new涓€涓柊鐨刾romise
const promise2 = new Promise((resolve, reject) => {
// then鏂规硶鍚屾鎵ц锛堝垽鏂槸鍚屾鐨勶級锛屽洖璋冨嚱鏁板紓姝ユ墽琛? if (this.status === RESOLVED) {
// then涓洖璋冨嚱鏁板紓姝ユ墽琛岋紝鍙互鐢?setTimeout 鎴?process.nextTick 妯℃嫙瀹炵幇銆愬彧鑳界敤涓€绉嶏紝涓嶈兘娣风敤銆? // ES6 瑙勮寖涓?then 鏄井浠诲姟锛岃繖閲屾棤娉曡嚜宸卞疄鐜颁竴涓井浠诲姟锛屽彧鑳借皟鐢ㄥ涓荤幆澧冩彁渚涚殑API锛坧rocess.nextTick锛?
// then鏂规硶鍚屾鎵ц鍒拌繖閲岋紝鍒涘缓鍖垮悕鍑芥暟鐨勬椂鍊欙紝promise2 杩樻病鏈夊畾涔夛紙绛夋瀯閫犲嚱鏁颁腑鐨勪唬鐮佸叏閮ㄦ墽琛屽畬姣曪紝鎵嶈兘鎷垮埌promise2锛? // 鏋勯€犲嚱鏁拌繕娌℃湁鎵ц瀹岋紝浣嗘槸鍦ㄦ瀯閫犲嚱鏁颁腑灏变娇鐢ㄤ簡瀹炰緥锛屽洜姝ゅ尶鍚嶅嚱鏁扮殑鎵ц涓€瀹氭槸寮傛鐨勶紝鎵嶈兘鍦ㄦ墽琛屾椂鎷垮埌瀹炰緥
// setTimeout(() => {
// try {
// const x = onResolved(this.value)
// log.debug("RESOLVED:then return x =", x)
// resolvePromise(promise2, x, resolve, reject)
// } catch (error) {
// reject(error)
// }
// }, 0)
process.nextTick(() => {
try {
// 鍥炶皟鍑芥暟寮傛鎵ц锛屽闈xecutor鐨則ry-catch鏃犳硶鎹曡幏鍒板紓甯革紝鍥犳闇€瑕佸湪婧愬ご鎹曡幏
const x = onResolved(this.value)
// 濡傛灉x鏄櫘閫氬€硷紝鍙互鐩存帴 resolve(x)
log.debug("RESOLVED:then return x =", x)
// 閫掑綊瑙f瀽鍥炶皟鍑芥暟鐨勮繑鍥炲€紉锛屽喅瀹歵hen杩斿洖鐨刾romise2鐨勭姸鎬? // 濡傛灉x鏄痯romise锛岃皟鐢ㄨpromise鐨則hen鏂规硶鏃讹紝浼犻€掔殑涓や釜鍙傛暟鍑芥暟灏辨槸褰撳墠then杩斿洖promise2鐨別xecutor涓彁渚涚殑resolve reject
// 1. 濡傛灉璇romise杩斿洖鎴愬姛锛屽垯璋冪敤褰撳墠then杩斿洖promise2鐨剅esolve鏂规硶锛屼娇褰撳墠then杩斿洖涓€涓垚鍔熺殑promise2
// 2. 濡傛灉璇romise杩斿洖澶辫触锛屽垯璋冪敤褰撳墠then杩斿洖promise2鐨剅eject鏂规硶锛屼娇褰撳墠then杩斿洖涓€涓け璐ョ殑promise2
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
// 鍙傛暟鍑芥暟寮傚父锛宼hen杩斿洖涓€涓け璐ョ殑promise2
log.error("RESOLVED: catch error:", error)
reject(error)
}
})
}
if (this.status === REJECTED) {
// setTimeout(() => {
// try {
// const x = onRejected(this.value)
// log.debug("REJECTED:then return x =", x)
// resolvePromise(promise2, x, resolve, reject)
// } catch (error) {
// reject(error)
// }
// }, 0)
process.nextTick(() => {
try {
const x = onRejected(this.value)
// 濡傛灉x鏄櫘閫氬€硷紝鍙互鐩存帴 resolve(x)
log.debug("REJECTED:then return x =", x)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
log.error("REJECTED: catch error:", error)
reject(error)
}
})
}
// 濡傛灉 executor 閲岄潰寮傛璋冪敤resolve鎴杛eject锛屽垯璋冪敤then鏂规硶鏃讹紝褰撳墠promise鏄痯ending鐘舵€? // 濡傛灉褰撳墠鐘舵€佹槸 pending锛岄渶瑕佺敤鍙戝竷璁㈤槄妯″紡锛屽垯灏嗕紶鍏ョ殑鍥炶皟鍑芥暟淇濆瓨璧锋潵锛岀◢鍚庢墽琛宺esolve鎴杛eject鏀瑰彉鐘舵€佹椂鍐嶈Е鍙戞墽琛? // 鍚屼竴涓猵romise鍙互澶氭璋冪敤 then 鏂规硶锛屽洜姝や細鏈夊涓洖璋冨嚱鏁帮紝闇€瑕佺敤鏁扮粍淇濆瓨
if (this.status === PENDING) {
// AOP
this.onResolvedCallbacks.push(() => {
// 涓嶆槸绔嬪嵆鎵ц锛屽綋鎵ц澶栭潰鐨勫尶鍚嶅嚱鏁扮殑鏃跺€欙紝鎵嶄細鎵ц
// do other things...
// setTimeout(() => {
// try {
// const x = onResolved(this.value)
// log.debug("PENDING->RESOLVED:then return x =", x)
// resolvePromise(promise2, x, resolve, reject)
// } catch (error) {
// reject(error)
// }
// }, 0)
process.nextTick(() => {
try {
const x = onResolved(this.value)
// 濡傛灉x鏄櫘閫氬€硷紝鍙互鐩存帴 resolve(x)
log.debug("PENDING->RESOLVED:then return x =", x)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
log.error("PENDING->RESOLVED: catch error:", error)
reject(error)
}
})
})
this.onRejectedCallbacks.push(() => {
// setTimeout(() => {
// try {
// const x = onRejected(this.value)
// log.debug("PENDING->REJECTED:then return x =", x)
// resolvePromise(promise2, x, resolve, reject)
// } catch (error) {
// reject(error)
// }
// }, 0)
process.nextTick(() => {
try {
const x = onRejected(this.value)
// 濡傛灉x鏄櫘閫氬€硷紝鍙互鐩存帴 resolve(x)
log.debug("PENDING->REJECTED:then return x =", x)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
log.error("PENDING->REJECTED: catch error:", error)
reject(error)
}
})
})
}
})
return promise2
}
//=============================================浠ヤ笅闈濸romise/A+ 瑙勮寖===============================================
// 杩斿洖涓€涓柊鐨刾romise锛屾牴鎹?onRejected 鐨勮繑鍥炵粨鏋滃喅瀹氳繑鍥瀙romise鐨勭姸鎬? catch(onRejected) {
// THIS鎸囦唬璋冪敤catch鐨刾romise瀹炰緥
return this.then(null, onRejected)
}
// node>10
// 琛ㄧず鍓嶉潰鐨刾romise鏃犺鎴愬姛杩樻槸澶辫触閮戒細鎵цfinally鏂规硶
// 褰撴棤璁哄浣曞繀椤昏澶勭悊涓€涓€昏緫鐨勬椂鍊欎娇鐢紝濡傛灉杩斿洖鎴愬姛鐨刾romise涓嶅奖鍝嶆暣涓猼hen閾剧殑缁撴灉
// callback
// 1. 璋冪敤callback涓嶄細浼犻€掑弬鏁帮紙鏃犳硶鎷垮埌鍓嶉潰promise鐨勮繑鍥炲€硷級
// 2. callback鏈€缁堝湪then鐨勫弬鏁板嚱鏁颁腑琚皟鐢? // 3. callback杩斿洖涓€涓猵romise锛堝鏋滀笉鏄垯鐢≒romise.resolve杞崲涓簆romise锛夛紝涓斾細绛夊緟杩欎釜promise杩斿洖
// finally鍊间紶閫掕鍒? // 璋冪敤then鏂规硶杩斿洖涓€涓猵romise锛屾牴鎹甤allback鐨勬墽琛岀粨鏋滃喅瀹氳嚜宸辩殑鐘舵€佸拰鍊? // 1. 濡傛灉callback杩斿洖鐨刾romise鎴愬姛锛屽垯finally杩斿洖鎴愬姛鐨刾romise锛屽€间负鍓嶉潰promise鐨勬垚鍔熺粨鏋滐紝浼犻€掍笅鍘伙紙閬靛惊 then 鐨勯摼寮忚皟鐢ㄥ師鐞嗭級
// 2. 濡傛灉callback杩斿洖鐨刾romise澶辫触锛屽垯finally杩斿洖澶辫触鐨刾romise锛屽€间负callback杩斿洖promise鐨勫け璐ュ師鍥狅紝鍙栦唬骞朵紶閫掍笅鍘伙紙閬靛惊 then 鐨勯摼寮忚皟鐢ㄥ師鐞嗭級
// 3. 濡傛灉callback鎵ц鎶ラ敊锛屽垯琚綋鍓峵hen鍥炶皟鐨則ry-catch鎹曡幏锛宖inally杩斿洖澶辫触鐨刾romise锛屽€间负鎶ラ敊鍘熷洜锛屽彇浠e苟浼犻€掍笅鍘? finally(callback) {
log.info(`call finally, promise is ${JSON.stringify(this)}`)
return this.then(value => {
log.debug("finally: previous promise is resolved")
// 濡傛灉鍓嶉潰promise鎴愬姛锛屽垯杩涘叆杩欓噷
// 鎵ц椤哄簭锛氬湪鍥炶皟鍑芥暟涓細
// 1.鎵ц callback()锛岃繑鍥炰竴涓€? // 2.鎵ц Promise.resolve()锛岃繑鍥炰竴涓猵romise
// 3.鎵ц then鏂规硶锛屽鐞嗗洖璋?鈥?)=>value鈥?
// 4.杩斿洖涓€涓?PENDING 鐘舵€佺殑promise銆傦紙姝ゆ椂瀵瑰闈㈢殑then鏂规硶鏉ヨ灏辨槸绗竴涓弬鏁板洖璋冭繑鍥炲€紉鏄竴涓猵romise锛岀户缁В鏋愶級
return Promise.resolve(callback()).then(() => value)
}, err => {
log.debug("finally: previous promise is rejected")
// 濡傛灉鍓嶉潰鐨刾romise澶辫触锛屽垯杩涘叆杩欓噷
return Promise.resolve(callback()).then(() => { throw err })
})
}
// 灏嗗綋鍓嶅€艰浆鎹负promise瀵硅薄锛歅romise.resolve([value])
// 鍙傛暟:
// 1. 鏄竴涓猵romise瀹炰緥锛屽垯鐩存帴鍘熸牱杩斿洖
// 2. 鏄竴涓猼henable瀵硅薄锛屽垯寮傛璋冪敤鍏秚hen鏂规硶,鍐冲畾resolve杩斿洖promise鐨勭姸鎬? // 2.1 Promise.resolve([thenable]) 鍙兘浼氳繑鍥炰竴涓け璐ョ殑promise
// 3. 涓嶆槸thenable瀵硅薄鎴杙romise瀹炰緥锛屽垯杩斿洖涓€涓柊鐨勬垚鍔熺殑promise锛屽€间负璇ュ弬鏁? // 4. 涓嶄紶鍙傛暟锛岃繑鍥炰竴涓柊鐨勬垚鍔熺殑promise锛屽€间负undefined
static resolve(value) {
// 涓嶅鐞嗗吋瀹? if (value instanceof Promise) {
// 鍘熸牱杩斿洖
return value
}
return new Promise((resolve, reject) => {
if (((typeof value === 鈥榦bject鈥?&& value !== null) || typeof value === 鈥榝unction鈥? &&
typeof value.then === 鈥榝unction鈥? {
// thenable 瀵硅薄
// 璋冪敤鍐呴儴then鏂规硶锛屽叾鍥炶皟鏄紓姝ユ墽琛岀殑锛岃€岃皟鐢╰henable瀵硅薄涓璽hen鏂规硶锛屽叾鍥炶皟鏄悓姝ョ殑(璋冪敤thenable.then灏变細鎵ц)
// 鍥犳杩欓噷闇€瑕佸湪璋冪敤鐨勬椂鍊欏紓姝ワ紙寰换鍔★級
// 璋冪敤鍐呴儴鐨則hen鏂规硶锛屾棤娉曞仛鎵嬭剼銆傝€宼henable瀵硅薄涓彲浠ュthen鏂规硶鍋氭墜鑴氾紝鍥犳杩欓噷瑕佹斁鍒皌ry-catch涓? process.nextTick(() => {
try {
value.then(resolve, reject)
} catch (error) {
reject(error)
}
})
} else {
return resolve(value)
}
})
}
// 灏嗗綋鍓嶅€艰浆鎹负涓€涓け璐ョ殑promise瀵硅薄锛歅romise.reject([value])
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
// 鍙傛暟锛氬疄鐜癷terator鎺ュ彛鐨勫彲杩唬瀵硅薄锛堟暟缁勩€佸瓧绗︿覆锛? // 1. 濡傛灉鍙傛暟涓嶅瓨鍦ㄦ垨鑰呬笉鍙凯浠o紝杩斿洖涓€涓け璐ョ殑promise锛屽€间负绫诲瀷閿欒
// 2. 濡傛灉鍙凯浠e璞℃垚鍛樹负绌猴紝杩斿洖涓€涓垚鍔熺殑promise锛屽€间负绌烘暟缁? // 3. 濡傛灉鍙凯浠e璞℃垚鍛樹笉鏄痯romise锛屽垯璋冪敤 Promise.resolve 灏嗗叾鍙樹负涓€涓猵romise
// 杩斿洖promise鐨勭姸鎬侊細鐢辨墍鏈夊彲杩唬瀵硅薄鐨勬垚鍛橈紙promise锛夌殑杩斿洖鐘舵€佸喅瀹? // 1. 鎵€鏈夋垚鍛榩romise閮借繑鍥炴垚鍔燂紝鍒檃ll杩斿洖涓€涓垚鍔熺殑promise锛屽€间负鎵€鏈夋垚鍛榩romise杩斿洖鍊肩粍鎴愮殑鏁扮粍锛堟寜鎴愬憳椤哄簭鎺掑簭锛? // 2. 鍙涓€涓垚鍛榩romise杩斿洖澶辫触锛屽垯all杩斿洖涓€涓け璐ョ殑promise锛屽€间负绗竴涓け璐ョ殑鎴愬憳promise鐨勫け璐ュ師鍥? // 3. 濡傛灉鎴愬憳promise鑷韩瀹氫箟浜哻atch鏂规硶锛岄偅涔堝畠琚玶ejected鏃朵細琚嚜韬畾涔夌殑catch鎹曡幏锛? // 骞惰繑鍥炰竴涓柊鐨刾romise锛堢敤杩欎釜鏂皃romise鐘舵€佷唬鏇胯鎴愬憳promise鐘舵€侊級
static all(promises) {
return new Promise((resolve, reject) => {
if (promises == undefined || !promises[Symbol.iterator]) {
const preReason = promises === undefined ? `${promises}` : `${typeof promises} ${promises}`
return reject(new TypeError(`${preReason} is not iterable (cannot read property Symbol(Symbol.iterator))`))
}
if (promises.length === 0) return resolve([])
let index = 0
const resultArr = []
function processValue(i, value) {
resultArr[i] = value
if (++index === promises.length) {
resolve(resultArr)
}
}
for (let i = 0; i < promises.length; i++) {
//promises[i] 鍙兘鏄櫘閫氬€硷紝鐢?Promise.resolve 鍖呬竴灞傦紝纭繚閮芥槸promise
Promise.resolve(promises[i]).then((value) => {
processValue(i, value)
}, (err) => {
// 鏈変竴涓け璐ュ垯缁撴潫寰幆
return reject(err)
})
}
})
}
// 鍙傛暟锛氬疄鐜癷terator鎺ュ彛鐨勫彲杩唬瀵硅薄锛堟暟缁勩€佸瓧绗︿覆锛? // 1. 濡傛灉鍙傛暟涓嶅瓨鍦ㄦ垨鑰呬笉鍙凯浠o紝杩斿洖涓€涓け璐ョ殑promise锛屽€间负绫诲瀷閿欒
// 2. 濡傛灉鍙凯浠e璞℃垚鍛樹负绌猴紝銆愯繑鍥炰竴涓狿ENDING 鐘舵€佺殑promise銆? // 3. 濡傛灉鍙凯浠e璞℃垚鍛樹笉鏄痯romise锛屽垯璋冪敤 Promise.resolve 灏嗗叾鍙樹负涓€涓猵romise
// 杩斿洖promise鐨勭姸鎬侊細
// 1. 鍙涓€涓垚鍛榩romise杩斿洖锛屽垯race杩斿洖鐩稿悓鐘舵€佺殑promise
static race(promises) {
return new Promise((resolve, reject) => {
if (promises == undefined || !promises[Symbol.iterator]) {
const preReason = promises === undefined ? `${promises}` : `${typeof promises} ${promises}`
return reject(new TypeError(`${preReason} is not iterable (cannot read property Symbol(Symbol.iterator))`))
}
if (promises.length === 0) return
for (let i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then((value) => {
return resolve(value)
}, (err) => {
return reject(err)
});
}
});
}
}
// 娴嬭瘯鍏ュ彛
// Promise鐨勫欢杩熷璞★紝娴嬭瘯鐨勬椂鍊欎細璋冪敤杩欎釜鍑芥暟
Promise.defer = Promise.deferred = function () {
const dfd = {}
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve
dfd.reject = reject
})
return dfd
}
module.exports = Promise
娴嬭瘯
鏇磋缁嗙殑娴嬭瘯鐢ㄤ緥鍙傝€價epo https://github.com/lfp1024/promise
resolve 瑙f瀽 promise
- resolve(promise) 鍙互閫掑綊瑙f瀽锛岀敱鍐呭眰promise鐨勭姸鎬佸喅瀹氬灞俻romise鐨勭姸鎬?/li>
- reject(promise) 涓嶄細閫掑綊瑙f瀽锛屽灞俻romise鐩存帴杩斿洖澶辫触锛屽け璐ュ師鍥犳槸promise
var p1 = new Promise(function (resolve, reject) {
resolve(new Promise(res => res(鈥榬esolve鈥?));
});
var p2 = new Promise(function (resolve, reject) {
// 灏唕esolve瀹炲弬promise鐨勭姸鎬佸彉涓鸿嚜宸辩殑鐘舵€侊紝灏嗗疄鍙俻romise鐨勫€煎彉涓鸿嚜宸辩殑鍊? resolve(new Promise((res, rej) => { rej(鈥榬eject鈥? }));
});
var p3 = new Promise(function (resolve, reject) {
reject(new Promise(res => res(鈥榬esolve鈥?));
});
p1.then(
function fulfilled(value) { console.log(鈥榩1 fulfilled: 鈥?+ value); },
function rejected(err) { console.log(鈥榩1 rejected: 鈥?+ err); }
);
p2.then(
function fulfilled(value) { console.log(鈥榩2 fulfilled: 鈥?+ value); },
function rejected(err) { console.log(鈥榩2 rejected: 鈥?+ err); }
);
p3.then(
function fulfilled(value) { console.log(鈥榩3 fulfilled: 鈥?+ value); },
function rejected(err) { console.log(鈥榩3 rejected: 鈥?+ err); }
);
// 杈撳嚭缁撴灉锛?// p3 rejected: [object Object]
// p1 fulfilled: resolve
// p2 rejected: reject
/*
瑙i噴锛?// 鍚屾浠g爜鎵ц
p1 鐨?resolve 娉ㄥ唽鍒颁笅涓€杞惊鐜墽琛?p2 鐨?resolve 娉ㄥ唽鍒颁笅涓€杞惊鐜墽琛?p3 鐨?reject 褰撳墠鎵ц鏍堜腑鍚屾鎵ц锛屽皢 p3.then 娉ㄥ唽鍒颁笅涓€杞惊鐜墽琛?
// 涓嬩竴杞惊鐜?p1 鐨?resolve 鎵ц锛屽皢 p1.then 娉ㄥ唽鍒颁笅涓€杞惊鐜墽琛?p2 鐨?resolve 鎵ц锛屽皢 p2.then 娉ㄥ唽鍒颁笅涓€杞惊鐜墽琛?p3.then 鎵ц锛岃緭鍑?=> p3 rejected: [object Object]
// 涓嬩竴杞惊鐜?p1.then 鎵ц锛岃緭鍑?=> p1 fulfilled: resolve
p2.then 鎵ц锛岃緭鍑?=> p2 rejected: reject
*/
resolve 瑙f瀽 thenable瀵硅薄
- ES6 鐨剅esolve鍙互瑙f瀽thenable瀵硅薄銆備笖thenable.then灞炰簬寰换鍔?/li>
- thenable.then鏂规硶涓殑鍙傛暟鍑芥暟鐨勬墽琛屾儏鍐典細鍐冲畾褰撳墠promise鐨勭姸鎬?/li>
console.log("--script start--")
let obj = {
then: function (onResolved, onRejected) {
console.log("寮傛鎵цthenable then")
onResolved(鈥樻垚鍔熷暒鈥?
}
}
setTimeout(() => {
console.log("setTimeout")
}, 0);
let p1 = new Promise(function (resolve, reject) {
console.log("1")
resolve(obj);
console.log("2")
});
p1.then(res=>{
console.log("promise then")
})
console.log("p1 =", p1)
setTimeout(() => {
console.log("p1 = ", p1)
}, 0);
console.log("--script end--")
// 浠庤緭鍑洪『搴忓彲浠ョ湅鍑鸿皟鐢╰henable鐨則hen鏂规硶灞炰簬寰换鍔?// --script start--
// 1
// 2
// p1 = Promise { <pending> }
// --script end--
// 寮傛鎵цthenable then
// promise then
// setTimeout
// p1 = Promise { 鈥樻垚鍔熷暒鈥?}
// 濡傛灉鏄畯浠诲姟锛屽垯杈撳嚭椤哄簭搴斾负锛堣皟鐢╮esolve涔嬪墠锛宲1.then灏氭湭娉ㄥ唽鍒颁簨浠堕槦鍒椾腑锛?// --script start--
// 1
// 2
// p1 = Promise { <pending> }
// --script end--
// setTimeout
// 寮傛鎵цthenable then
// promise then
// p1 = Promise { 鈥樻垚鍔熷暒鈥?}
then 閫掑綊瑙f瀽 promise
- then 浼氶€掑綊瑙f瀽鍏跺洖璋冨嚱鏁拌繑鍥炵殑promise銆傛渶鍐呭眰promise鐨勭姸鎬佸喅瀹氬灞倀hen杩斿洖promise鐨勭姸鎬?/li>
let p = new Promise((resolve, reject) => {
resolve(1)
})
// [resolve(promise)]-------------------------------------------------
// 3灞俻romise锛氭渶澶栧眰p1锛屼腑闂村眰p2(then鐨勭涓€涓洖璋冭繑鍥炵殑promise)锛屾渶鍐呭眰p3锛?绉掑悗鎴愬姛鎴栧け璐ワ級
let p1 = p.then(value => {
// then鐨勫弬鏁板嚱鏁拌繑鍥炰竴涓?new Promise
return new Promise((resolve, reject) => {
setTimeout(() => {
// resolve 鍙堣繑鍥炰竴涓猵romise锛岄€掑綊瑙f瀽
resolve(new Promise((resolve, reject) => {
setTimeout(() => {
// 鏈€鍐呭眰promise璋冪敤resolve鎴愬姛涔嬪悗锛屼細鎵ц鍏秚hen鐨勭涓€涓洖璋冿紝鍗虫墽琛屼腑闂村眰p2鐨剅esolve
// resolve("success")
// 鏈€鍐呭眰promise璋冪敤reject澶辫触涔嬪悗锛屼細鎵ц鍏秚hen鐨勭浜屼釜鍥炶皟锛屽嵆鎵ц涓棿灞俻2鐨剅eject
reject("fail")
}, 1000);
}))
}, 1000);
})
})
// 澶栭潰鎯宠鑾峰彇褰撳墠then杩斿洖promise鐨勭粨鏋滐紝杩樻槸瑕佽皟鐢ㄥ綋鍓峵hen杩斿洖promise鐨則hen鏂规硶
p1.then(res => {
console.log("褰撳墠then杩斿洖promise鐨勭粨鏋?", res) // 褰撳墠then杩斿洖promise鐨勭粨鏋? success
}, err => {
console.log("褰撳墠then杩斿洖promise鐨勫師鍥?", err) // 褰撳墠then杩斿洖promise鐨勫師鍥? fail
})
// [reject(promise)]-------------------------------------------------
let promise = new Promise((resolve, reject) => {
resolve(1)
})
let promise2 = promise.then(value => {
// then鐨勫弬鏁板嚱鏁拌繑鍥炰竴涓?new Promise
return new Promise((resolve, reject) => {
setTimeout(() => {
// reject 鍙堣繑鍥炵殑涓€涓猵romise锛屼笉鍐嶉€掑綊瑙f瀽锛堜絾鏄細鎵цnew琛ㄨ揪寮忥紝鎵ц瀹屽悗绔嬪嵆杩斿洖涓€涓?PENDING 鐘舵€佺殑promise锛? reject(new Promise((resolve, reject) => {
console.log("鎵ц")
setTimeout(() => {
resolve("success")
}, 1000);
}))
}, 1000);
})
})
// 澶栭潰鎯宠鑾峰彇褰撳墠then杩斿洖promise鐨勭粨鏋滐紝杩樻槸瑕佽皟鐢ㄥ綋鍓峵hen杩斿洖promise鐨則hen鏂规硶
promise2.then(res => {
console.log("褰撳墠then杩斿洖promise鐨勭粨鏋?", res)
}, err => {
console.log("褰撳墠then杩斿洖promise鐨勫師鍥?", err) // 褰撳墠then杩斿洖promise鐨勫師鍥? Promise { <pending> }
})
then 瑙f瀽 thenable 瀵硅薄
- then瑙f瀽 thenable 寮傛璋冪敤鍏秚hen 鏂规硶
console.log("--script start--")
let obj = {
then: function (onResolved, onRejected) {
console.log("寮傛鎵цthenable then")
onResolved(鈥樻垚鍔熷暒鈥?
// onRejected(鈥樺け璐ュ暒鈥?
// throw Error("Oops!")
}
}
setTimeout(() => {
console.log("setTimeout")
}, 0)
let p = Promise.resolve(鈥榦k鈥?
let p1 = p.then(res => {
console.log("p2 then")
return obj
})
let p2 = Promise.resolve(鈥榦k2鈥?
let p3 = p2.then(res => {
console.log("p3 then")
return
})
console.log("p1 =", p1)
setTimeout(() => {
console.log("p1 = ", p1)
}, 0)
console.log("--script end--")
// 杈撳嚭锛?// --script start--
// p1 = Promise { <pending> }
// --script end--
// p2 then
// p3 then
// 寮傛鎵цthenable then
// setTimeout
// p1 = Promise { 鈥樻垚鍔熷暒鈥?}
// 濡傛灉涓嶆槸寮傛璋冪敤锛岄『搴忔槸锛?// --script start--
// p1 = Promise { <pending> }
// --script end--
// p2 then
// 寮傛鎵цthenable then
// p3 then
// setTimeout
// p1 = Promise { 鈥樻垚鍔熷暒鈥?}
let fs = require(鈥榝s鈥?
// 闇€姹傛槸璇诲彇涓€涓枃浠惰幏鍙栬矾寰勶紝鐒跺悗鍐嶇户缁鍙栧唴瀹?// 褰撳墠璺緞涓嬫湁涓や釜鏂囦欢 name.txt 鍜?age.txt銆俷ame.txt 鍐呭鏄?age.txt銆俛ge.txt 鍐呭鏄?27銆?// 鍏堣鍙?name.txt 鎷垮埌 age.txt锛屽啀璇诲彇 age.txt 鍐呭
fs.readFile(鈥?/name.txt鈥? 鈥榰tf-8鈥? (err, data) => {
if (err) {
// 閿欒澶勭悊...
}
console.log("data = ", data)
fs.readFile(data, 鈥榰tf-8鈥? (err, data) => {
if (err) {
// 閿欒澶勭悊...
}
console.log("data = ", data)
})
})
function readFileSync(filePath) {
return new Promise((res, rej) => {
fs.readFile(filePath, 鈥榰tf-8鈥? (err, data) => {
if (err) return rej(err)
return res(data)
})
})
}
readFileSync(鈥?/name.txt鈥?.then((data) => {
console.log(鈥樿幏鍙栧埌鏁版嵁鈥? data)
return readFileSync(data)
}).then((data) => {
console.log(鈥樿幏鍙栧埌鏁版嵁鈥? data)
}, (err) => {
console.log(鈥樺け璐モ€? err)
})
/*
鐢?setTimeout 瀹炵幇then鐨勫紓姝ヨ皟鐢紙瀹忎换鍔★級锛岃窡es6鎵ц椤哄簭涓嶅悓
杈撳嚭缁撴灉锛?data = age.txt
data = 27
鑾峰彇鍒版暟鎹?age.txt
鑾峰彇鍒版暟鎹?27
鍒嗘瀽锛?
// 绗竴杞?
fs.readFile 娣诲姞涓€涓畯浠诲姟1锛堣鍙栧埌鏁版嵁涔嬪悗瑙﹀彂锛?readFileSync 娣诲姞涓€涓畯浠诲姟2锛堣鍙栧埌鏁版嵁涔嬪悗瑙﹀彂锛?// 绗簩杞?璇诲彇鍒版暟鎹?
瀹忎换鍔?鎵ц锛岃緭鍑?>data = age.txt锛屾坊鍔犲畯浠诲姟3
瀹忎换鍔?鎵ц锛屾坊鍔犲畯浠诲姟4锛坱hen锛?// 绗笁杞?瀹忎换鍔?鎵ц锛岃緭鍑?>data = 27
// 绗洓杞?瀹忎换鍔?鎵ц锛岃緭鍑?>鑾峰彇鍒版暟鎹?age.txt锛屾坊鍔犲畯浠诲姟5
// 绗簲杞?瀹忎换鍔?鎵ц锛屾坊鍔犲畯浠诲姟6锛坱hen锛?// 绗叚杞?瀹忎换鍔?鎵ц锛岃緭鍑?>鑾峰彇鍒版暟鎹?27
*/
/*
鎹㈢敤 process.nextTick 鏉ュ疄鐜板垯鎵ц椤哄簭鐩稿悓
杈撳嚭缁撴灉锛?data = age.txt
鑾峰彇鍒版暟鎹?age.txt
data = 27
鑾峰彇鍒版暟鎹?27
鍒嗘瀽锛?// 绗竴杞?
fs.readFile 娣诲姞涓€涓畯浠诲姟1锛堣鍙栧埌鏁版嵁涔嬪悗瑙﹀彂锛?readFileSync 娣诲姞涓€涓畯浠诲姟2锛堣鍙栧埌鏁版嵁涔嬪悗瑙﹀彂锛?// 绗簩杞?璇诲彇鍒版暟鎹?
瀹忎换鍔?鎵ц锛岃緭鍑?>data = age.txt锛屾坊鍔犲畯浠诲姟3
瀹忎换鍔?鎵ц锛屾坊鍔犲井浠诲姟1锛坱hen锛?// 绗笁杞?寰换鍔?鎵ц锛岃緭鍑?>鑾峰彇鍒版暟鎹?age.txt锛屾坊鍔犲畯浠诲姟4
// 绗洓杞?瀹忎换鍔?鎵ц锛岃緭鍑?>data = 27
// 绗簲杞?瀹忎换鍔?鎵ц锛屾坊鍔犲井浠诲姟2锛坱hen锛?// 绗叚杞?寰换鍔?鎵ц锛岃緭鍑?>鑾峰彇鍒版暟鎹?27
*/
Promise.resolve 瑙f瀽 promise
- Promise.resolve 瑙f瀽promise
- Promise.reject 涓嶈В鏋恜romise
var p1 = new Promise(function (resolve, reject) {
resolve(Promise.resolve(鈥榬esolve鈥?);
});
var p2 = new Promise(function (resolve, reject) {
resolve(Promise.reject(鈥榬eject鈥?);
});
var p3 = new Promise(function (resolve, reject) {
reject(Promise.resolve(鈥榬esolve鈥?);
});
p1.then(
function fulfilled(value) { console.log(鈥榩1 fulfilled: 鈥?+ value); },
function rejected(err) { console.log(鈥榩1 rejected: 鈥?+ err); }
);
p2.then(
function fulfilled(value) { console.log(鈥榩2 fulfilled: 鈥?+ value); },
function rejected(err) { console.log(鈥榩2 rejected: 鈥?+ err); }
);
p3.then(
function fulfilled(value) { console.log(鈥榩3 fulfilled: 鈥?+ value); },
function rejected(err) { console.log(鈥榩3 rejected: 鈥?+ err); }
);
// p3 rejected: [object Promise]
// p1 fulfilled: resolve
// p2 rejected: reject
https://promisesaplus.com/
https://github.com/YvetteLau/Blog/issues/2
var p1 = new Promise(function (resolve, reject) {
resolve(Promise.resolve(鈥榬esolve鈥?);
});
var p2 = new Promise(function (resolve, reject) {
resolve(Promise.reject(鈥榬eject鈥?);
});
var p3 = new Promise(function (resolve, reject) {
reject(Promise.resolve(鈥榬esolve鈥?);
});
p1.then(
function fulfilled(value) { console.log(鈥榩1 fulfilled: 鈥?+ value); },
function rejected(err) { console.log(鈥榩1 rejected: 鈥?+ err); }
);
p2.then(
function fulfilled(value) { console.log(鈥榩2 fulfilled: 鈥?+ value); },
function rejected(err) { console.log(鈥榩2 rejected: 鈥?+ err); }
);
p3.then(
function fulfilled(value) { console.log(鈥榩3 fulfilled: 鈥?+ value); },
function rejected(err) { console.log(鈥榩3 rejected: 鈥?+ err); }
);
// p3 rejected: [object Promise]
// p1 fulfilled: resolve
// p2 rejected: reject
https://github.com/YvetteLau/Blog/issues/2
以上是关于鏍规嵁 Promise/A+ 鍜?ES6 瑙勮寖锛屽疄鐜?Promise 婧愮爜锛堥檮璇︾粏娉ㄩ噴鍜屾祴璇曪級的主要内容,如果未能解决你的问题,请参考以下文章
鍓嶇涔嬭矾锛氱敤 Angular 瑙勮寖鏉ョ害鏉熷洟闃?git 鎻愪氦
鑵捐 Git 瑙勮寖鍑虹倝锛屽啓缁欏紑鍙戣€呯殑 Git 鎸囧崡!