Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vmstarchenko@edu.hse.ru task2 #22

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
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
90 changes: 90 additions & 0 deletions lib/SP2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
'use strict';
// NO REQUIRE

class SuperPromise {
constructor(executor) {
this.state = 0;
this.work = 0; // pending
this.chain = [];
try {
let result = executor(this.resolve.bind(this), this.reject.bind(this));
this.state = 1;
} catch(e) {
this.state = 2;
}
this._check_chain();
}

dummy() {}

_check_chain() {
if (this.work === 0 && this.chain.length !== 0) {
this.work = 1;
let promise = this.chain.pop(0);
setTimeout(() => {
if (this.state === 1) {
try {
promise.def();
} catch(e) {
this.state = 2;
}
}
if (this.state === 2) {
promise.err();
}
this.work = 0;
this._check_chain();
}, 0);
}
}

then(onResolve, onRejection) {
this.chain.push({
def: onResolve,
err: onRejection ? onRejection : this.dummy,
});
this._check_chain();
return this;
}

catch(onRejection) {
return this.then(undefined, onRejection);
}

/* PART 2 */
static resolve(val) {
return new Promise(function (resolve) {
resolve(val);
});
}

static reject(val) {
return new Promise(function (resolve) {
resolve(val);
});
}

static all(data) {
let promise = new Promise(function () {});
for (let i = 0, size = data.length; i < size; ++i) {
promise.then(data[i]);
}
return promise;
}

static race() {
// Your code here...
}

/* PART 3 */
static queue() {

}

static stack() {

}
}

// module.exports = Promise; // TODO: kek
module.exports = SuperPromise; // TODO: kek
214 changes: 192 additions & 22 deletions lib/SuperPromise.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,214 @@
'use strict';
// NO REQUIRE

class SuperPromise {
constructor(executor) {

}
var DEBUG = false;

then(onResolve) {
function callAsync(func, context, ...args) {
setTimeout(() => func.call(context, ...args), 1);
}

var idCounter = 0;
class SuperPromise {
constructor(executor) {
this.promiseId = idCounter++;
if (DEBUG) console.log('promise', this.promiseId);
this.state = 0; // 0 - wait, 1 - finished, 2 - rejected
this.promises = [];
this.result = undefined;
if (executor) {
executor(this.resolve.bind(this), this.reject.bind(this));
}
}

catch(onRejection) {
dummy() {}

solve() {
if (DEBUG) console.log('solve', this.state);
if (this.state !== 0) {
this.promises = this.promises.reverse();
while (this.promises[0]) {
// if (DEBUG) console.log(this.promises[0], this.promises.pop(0));
if (DEBUG) console.log('st', this.state, this.promises.length);
if (this.state === 1) {
callAsync(this.promises.pop().def);
} else if (this.state === 2) {
callAsync(this.promises.pop().err);
}
}
}
this.promises = undefined;
}

/* PART 2 */
static resolve() {
// Your code here...
then(onFulfilled, onRejection) {
if (DEBUG) console.log('then', this.state);
let nextPromise = new this.constructor();
let promise = {
def: (() => {
if (DEBUG) console.log('on solve');
if (typeof onFulfilled === 'function') {
try {
nextPromise.resolve(onFulfilled(this.result));
} catch (e) {
nextPromise.reject(e);
}
} else {
nextPromise.resolve(this.result);
}
}),
err: (() => {
if (typeof onRejection === 'function') {
try {
nextPromise.resolve(onRejection(this.result));
} catch (e) {
nextPromise.reject(e);
}
} else {
nextPromise.reject(this.result);
}
})
};
if (this.state === 0) {
this.promises.push(promise);
} else if (this.state === 1) {
callAsync(promise.def);
} else if (this.state === 2) {
callAsync(promise.err);
}
return nextPromise;
}

static reject() {
// Your code here...
}
catch(onRejection) {
return this.then(undefined, onRejection);
}

static all() {
// Your code here...
}
/* PART 2 */
resolve(val) {
if (this.state !== 0)
return;
this.state = 1;
this.result = val;
this.solve();
return this;
}

static race() {
// Your code here...
}
static resolve(val) {
return new Promise(function (resolve) {
resolve(val);
});
}

reject(val) {
if (DEBUG) console.log('on reject', this.state);
if (this.state !== 0)
return;
this.state = 2;
this.result = val;
this.solve();
return this;
}

/* PART 3 */
static queue() {
static reject(val) {
return new Promise(function (resolve, reject) {
reject(val);
});
}

static all(data) {
let promise = new SuperPromise(function () {});
let size = data.length;
let resolvedNumber = 0;
if (DEBUG) console.log('all...', data, size);
if (size === 0) {
return promise.resolve(data);
}
for (let i = 0; i < size; ++i) {
if (data[i] && data[i].then) {
if (DEBUG) console.log(data[i], data[i].then);
data[i].then((d) => {
if (DEBUG) console.log(2);
++resolvedNumber;
if (size === resolvedNumber) {
return promise.resolve(d);
}
}, (d) => {
return promise.reject(d);
});
} else {
++resolvedNumber;
}
if (size === resolvedNumber) {
return promise.resolve(data);
}
// promise.then(data[i]);
}
return promise;
}

static stack() {
static race(data) {
// Your code here...
let promise = new SuperPromise(function () {});
let size = data.length;
let resolvedNumber = 0;
if (DEBUG) console.log('race...', data, size);
if (size === 0) {
return promise.resolve(data);
}
for (let i = 0; i < size; ++i) {
if (data[i] && data[i].then) {
data[i].then((d) => {
return promise.resolve(d);
}, (d) => {
++resolvedNumber;
return promise.reject(d);
});
} else {
++resolvedNumber;
return promise.resolve(data[i]);
}
}
return promise;
}

/* PART 3 */
static queue(data) {
if (DEBUG) console.log(data);
if (!data)
return SuperPromise.resolve();
let size = data.length;
if (size === 0)
return SuperPromise.resolve();
let currentPromise = SuperPromise.resolve(), lastPromise;
lastPromise = currentPromise;
if (DEBUG) console.log(data);
let i, result;
for (i = size-1; i >= 0; --i) {
if (DEBUG) console.log(i);
if (data[i].then) {
result = data[i].then(
((nextPromise) => ((d) => nextPromise.then(d)))(currentPromise),
(d) => {if (DEBUG) console.log('error'); i = -2; return d;}
);
}
else {
return SuperPromise.resolve();
}
if (i !== 0)
currentPromise = data[i];
}
if (DEBUG) console.log('end', i);
if (i === -2)
if (DEBUG) console.log('do');
return currentPromise;
}

static stack() {

}
}

module.exports = Promise; // TODO: kek
// var x = new SuperPromise(), a, b, c;
// a = x.then(undefined, () => if (DEBUG) console.log(1));
// b = x.then(undefined, () => if (DEBUG) console.log(2));
// c = x.then(undefined, () => if (DEBUG) console.log(3));
// module.exports = Promise; // TODO: kek
module.exports = SuperPromise; // TODO: kek
11 changes: 11 additions & 0 deletions lib/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Document</title>
</head>
<body>
<script src="SuperPromise.js">
</script>
</body>
</html>
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"task_4": "NODE_PATH=. node tasks/task_4.js",
"test_base": "part-1-task-2-test-1 lib/testPromise",
"test_advanced": "part-1-task-2-test-2 lib/testPromise && npm run test_static",
"test_static_c": "npm run test_static",
"test_static": "part-1-task-2-test-3 lib/testPromise",
"test_bonus": "part-1-task-2-test-4 lib/testPromise",
"test": "npm run test_advanced && npm run test_bonus"
Expand Down