Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,25 @@
demo
node_modules
node_modules

# Editor、mac files
.idea/
.DS_Store

# local env files
.env.local
.env.*.local

# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
Footer
140 changes: 140 additions & 0 deletions PromiseA.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
const STATUS = {
PENDING: 'pending',
FULFILLED: 'fulfilled',
REJECTED: 'rejected',
}

function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
reject(new TypeError("The promise and the return value are the same"))
}

if (typeof x === 'object' || typeof x === 'function') {
if (x === null){
return resolve(x)
}

let then
try {
then = x.then
} catch (err) {
return reject(err)
}

if (typeof then === "function") {
let called = false
try {
then.call(x, y => {
if (called) {
return
}
called = true
resolvePromise(promise2, y, resolve, reject)
}, err => {
if (called) {
return
}
called = true
reject(err)
})
} catch (err) {
if (called) {
return
}
reject(err)
}
} else {
resolve(x)
}
} else {
resolve(x)
}
}

class MyPromise {
status = STATUS.PENDING
value = null
reason = null

constructor(executor) {
executor(this.resolve, this.reject)
}

resolve = value => {
if (this.status === STATUS.PENDING) {
this.status = STATUS.FULFILLED
this.value = value

while (this.onFullFilledCallback.length) {
this.onFullFilledCallback.shift()(value)
}
}
}

reject = (reason) => {
if (this.status === STATUS.PENDING) {
this.status = STATUS.REJECTED
this.reason = reason

while (this.onRejectedCallback.length) {
this.onRejectedCallback.shift()(reason)
}}

}

onFullFilledCallback = []
onRejectedCallback = []

then = function (onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
onRejected = typeof onRejected === "function" ? onRejected : error => { throw error }

const promise2 = new MyPromise((resolve, reject) => {

const fulfilledMicrotask = () => {
queueMicrotask(() => {
try {
const x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
})
}

const rejectedMicrotask = () => {
queueMicrotask(() => {
try {
const x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
})
}

if (this.status === STATUS.PENDING) {
this.onFullFilledCallback.push(fulfilledMicrotask)
this.onRejectedCallback.push(rejectedMicrotask)
} else if (this.status === STATUS.FULFILLED) {
fulfilledMicrotask()
} else if (this.status === STATUS.REJECTED) {
rejectedMicrotask()
}
})

return promise2
}
}

MyPromise.deferred = function () {
const result = {}
result.promise = new MyPromise(function (resolve, reject) {
result.resolve = resolve
result.reject = reject
})

return result
}

module.exports = MyPromise
82 changes: 70 additions & 12 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
function myPromise(constructor) {
const STATUS_PENDING = 'pending';
const STATUS_FULFILLED = 'fulfilled';
const STATUS_REJECTED = 'rejected';

function MyPromise(constructor) {
let self = this;

self.status = "pending" //定义状态改变前的初始状态

self.value = undefined;//定义状态为resolved的时候的状态

self.reason = undefined;//定义状态为rejected的时候的状态
self.value = undefined; //定义状态为resolved的时候的状态

function resolve(value) {
self.reason = undefined; //定义状态为rejected的时候的状态

// TODO resolve如何改变状态及返回结果
self.resolveCallbacks = [];
self.rejectCallbacks = [];

function resolve(value) {
if (self.status === STATUS_PENDING) {
self.status = 'fulfilled';
self.value = value;
self.resolveCallbacks.forEach(fn => fn(self.value));
}
}

function reject(reason) {

// TODO reject如何改变状态及返回结果

if (self.status === STATUS_PENDING) {
self.status = 'rejected';
self.reason = reason;
self.rejectCallbacks.forEach(fn => fn(self.reason));
}
}

//捕获构造异常
Expand All @@ -33,9 +44,56 @@ function myPromise(constructor) {

}

myPromise.prototype.then = function (onFullfilled, onRejected) {
MyPromise.prototype.then = function (onFullfilled, onRejected) {
onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : (v) => v;
onRejected = typeof onRejected === 'function' ? onRejected : (e) => e;

if (this.status === 'pending') {
const p = new MyPromise((resolve, reject) => {
this.resolveCallbacks.push(() => {
try {
const newValue = onFullfilled(this.value);
resolve(newValue);
} catch (e) {
reject(e)
}
});

this.rejectCallbacks.push(() => {
try {
const newReason = onRejected(this.reason)
reject(newReason)
} catch (e) {
reject(e)
}
});
});
return p;
}

//TODO then如何实现
if (this.status === STATUS_FULFILLED) {
const p = new MyPromise((resolve, reject) => {
try {
const newValue = onFullfilled(this.value);
resolve(newValue);
} catch (e) {
reject(e);
}
});
return p;
}

if (this.status === STATUS_REJECTED) {
const p = new MyPromise((resolve, reject) => {
try {
const newReason = onRejected(this.reason);
reject(newReason);
} catch (e) {
reject(e);
}
});
return p;
}
}
module.exports = myPromise

module.exports = MyPromise;
9 changes: 5 additions & 4 deletions index.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
const myPromise = require('./index');
const MyPromise = require('./index');

var p = new myPromise(function (resolve, reject) { resolve('isOk') });
test('测试primose的then是否成功', () => {
const p = new MyPromise(function (resolve, reject) { resolve('isOk') });

test('测试 primose 的 then 是否成功', () => {
expect.assertions(1);
return p.then(data => {
expect(data).toBe('isOk');
});
});
});
Loading