Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
R
rsvp.js
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
rsvp.js
Compare Revisions
master...wipromain
Source
wipromain
Select Git revision
...
Target
master
Select Git revision
Compare
Commits (1)
WIP monitor pattern
· 58066429
Romain Courteaud
authored
Jun 02, 2014
58066429
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
343 additions
and
3 deletions
+343
-3
rsvp.js
lib/rsvp.js
+2
-1
watcher.js
lib/rsvp/watcher.js
+112
-0
extension_test.js
test/tests/extension_test.js
+229
-2
No files found.
lib/rsvp.js
View file @
58066429
...
...
@@ -4,6 +4,7 @@ import { Promise } from "./rsvp/promise";
import
{
denodeify
}
from
"./rsvp/node"
;
import
{
all
,
any
}
from
"./rsvp/all"
;
import
{
Queue
,
ResolvedQueueError
}
from
"./rsvp/queue"
;
import
{
Monitor
,
ResolvedMonitorError
}
from
"./rsvp/watcher"
;
import
{
delay
,
timeout
}
from
"./rsvp/timeout"
;
import
{
hash
}
from
"./rsvp/hash"
;
import
{
rethrow
}
from
"./rsvp/rethrow"
;
...
...
@@ -16,4 +17,4 @@ function configure(name, value) {
config
[
name
]
=
value
;
}
export
{
CancellationError
,
Promise
,
EventTarget
,
all
,
any
,
Queue
,
ResolvedQueueError
,
delay
,
timeout
,
hash
,
rethrow
,
defer
,
denodeify
,
configure
,
resolve
,
reject
};
export
{
CancellationError
,
Promise
,
EventTarget
,
all
,
any
,
Queue
,
ResolvedQueueError
,
Monitor
,
ResolvedMonitorError
,
delay
,
timeout
,
hash
,
rethrow
,
defer
,
denodeify
,
configure
,
resolve
,
reject
};
lib/rsvp/watcher.js
0 → 100644
View file @
58066429
import
{
Promise
}
from
"./promise"
;
import
{
Queue
}
from
"./queue"
;
import
{
CancellationError
}
from
"./cancellation_error"
;
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
function
ResolvedMonitorError
(
message
)
{
this
.
name
=
"resolved"
;
if
((
message
!==
undefined
)
&&
(
typeof
message
!==
"string"
))
{
throw
new
TypeError
(
'You must pass a string.'
);
}
this
.
message
=
message
||
"Default Message"
;
}
ResolvedMonitorError
.
prototype
=
new
Error
();
ResolvedMonitorError
.
prototype
.
constructor
=
ResolvedMonitorError
;
function
isFunction
(
x
){
return
typeof
x
===
"function"
;
}
var
Monitor
=
function
()
{
var
monitor
=
this
,
promise_list
=
[],
promise
,
reject
,
notify
,
resolved
;
if
(
!
(
this
instanceof
Monitor
))
{
return
new
Monitor
();
}
function
canceller
()
{
var
len
=
promise_list
.
length
,
i
;
for
(
i
=
0
;
i
<
len
;
i
+=
1
)
{
promise_list
[
i
].
cancel
();
}
// Clean it to speed up other canceller run
promise_list
=
[];
}
promise
=
new
Promise
(
function
(
done
,
fail
,
progress
)
{
reject
=
function
(
rejectedReason
)
{
if
(
resolved
)
{
return
;}
monitor
.
isRejected
=
true
;
monitor
.
rejectedReason
=
rejectedReason
;
resolved
=
true
;
canceller
();
return
fail
(
rejectedReason
);
};
notify
=
progress
;
},
canceller
);
monitor
.
cancel
=
function
()
{
if
(
resolved
)
{
return
;}
resolved
=
true
;
promise
.
cancel
();
promise
.
fail
(
function
(
rejectedReason
)
{
monitor
.
isRejected
=
true
;
monitor
.
rejectedReason
=
rejectedReason
;
});
};
monitor
.
then
=
function
()
{
return
promise
.
then
.
apply
(
promise
,
arguments
);
};
monitor
.
monitor
=
function
(
promise_to_monitor
)
{
if
(
resolved
)
{
throw
new
ResolvedMonitorError
();
}
var
queue
=
new
Queue
()
.
push
(
function
()
{
return
promise_to_monitor
;
})
.
push
(
function
(
fulfillmentValue
)
{
// Promise to monitor is fullfilled, remove it from the list
var
len
=
promise_list
.
length
,
promise_to_monitor
,
new_promise_list
=
[],
i
;
for
(
i
=
0
;
i
<
len
;
i
+=
1
)
{
promise_to_monitor
=
promise_list
[
i
];
if
(
!
(
promise_to_monitor
.
isFulfilled
||
promise_to_monitor
.
isRejected
))
{
new_promise_list
.
push
(
promise_to_monitor
);
}
}
promise_list
=
new_promise_list
;
},
function
(
rejectedReason
)
{
if
(
rejectedReason
instanceof
CancellationError
)
{
if
(
!
(
promise_to_monitor
.
isFulfilled
&&
promise_to_monitor
.
isRejected
))
{
// The queue could be cancelled before the first push is run
promise_to_monitor
.
cancel
();
}
}
reject
(
rejectedReason
);
throw
rejectedReason
;
},
function
(
notificationValue
)
{
notify
(
notificationValue
);
return
notificationValue
;
});
promise_list
.
push
(
queue
);
return
this
;
};
};
Monitor
.
prototype
=
Object
.
create
(
Promise
.
prototype
);
Monitor
.
prototype
.
constructor
=
Monitor
;
export
{
Monitor
,
ResolvedMonitorError
};
test/tests/extension_test.js
View file @
58066429
...
...
@@ -2294,7 +2294,7 @@ describe("`RSVP.Queue`", function () {
it
(
'should be fulfilled when the queue is empty'
,
function
(
done
)
{
var
queue
=
new
RSVP
.
Queue
();
queue
.
push
(
function
()
{
return
RSVP
.
delay
(
3
0
);
return
RSVP
.
delay
(
2
0
);
});
setTimeout
(
function
()
{
...
...
@@ -2341,7 +2341,7 @@ describe("`RSVP.Queue`", function () {
it
(
'should be rejected if one entry is rejected'
,
function
(
done
)
{
var
queue
=
new
RSVP
.
Queue
();
queue
.
push
(
function
()
{
return
RSVP
.
timeout
(
3
0
);
return
RSVP
.
timeout
(
2
0
);
});
setTimeout
(
function
()
{
...
...
@@ -2439,3 +2439,230 @@ describe("`RSVP.Queue`", function () {
});
});
});
describe
(
"`RSVP.Monitor`"
,
function
()
{
describe
(
"`ResolvedMonitorError`"
,
function
()
{
describe
(
"`ResolvedMonitorError` constructor"
,
function
()
{
it
(
'should exist and have length 1'
,
function
()
{
assert
(
RSVP
.
ResolvedMonitorError
);
assert
.
equal
(
RSVP
.
ResolvedMonitorError
.
length
,
1
);
});
it
(
'should be a constructor'
,
function
()
{
var
error
=
new
RSVP
.
ResolvedMonitorError
();
assert
.
equal
(
Object
.
getPrototypeOf
(
error
),
RSVP
.
ResolvedMonitorError
.
prototype
,
'[[Prototype]] equals ResolvedMonitorError.prototype'
);
assert
.
equal
(
error
.
constructor
,
RSVP
.
ResolvedMonitorError
,
'constructor property of instances is set correctly'
);
assert
.
equal
(
RSVP
.
ResolvedMonitorError
.
prototype
.
constructor
,
RSVP
.
ResolvedMonitorError
,
'constructor property of prototype is set correctly'
);
});
it
(
'should throw a `TypeError` if not given a string'
,
function
()
{
assert
.
throws
(
function
()
{
var
error
=
new
RSVP
.
ResolvedMonitorError
({});
// ... jslint forces to use the variable
error
.
foo
=
"bar"
;
},
TypeError
);
});
it
(
'should be throwable'
,
function
()
{
assert
.
throws
(
function
()
{
throw
new
RSVP
.
ResolvedMonitorError
();
},
RSVP
.
ResolvedMonitorError
);
});
});
describe
(
"`ResolvedMonitorError` instance"
,
function
()
{
it
(
'must be an instance of Error'
,
function
()
{
var
error
=
new
RSVP
.
ResolvedMonitorError
();
assert
(
error
instanceof
Error
);
});
it
(
'must have a `name` property with value `resolved`'
,
function
()
{
var
error
=
new
RSVP
.
ResolvedMonitorError
();
assert
.
equal
(
error
.
name
,
"resolved"
);
});
it
(
'must have a `message` property with the message value'
,
function
()
{
var
error
=
new
RSVP
.
ResolvedMonitorError
(
"Foo"
);
assert
.
equal
(
error
.
message
,
"Foo"
);
});
it
(
'must have a default `message` property to `Default Message`'
,
function
()
{
var
error
=
new
RSVP
.
ResolvedMonitorError
();
assert
.
equal
(
error
.
message
,
"Default Message"
);
});
});
});
describe
(
"`Monitor` constructor"
,
function
()
{
it
(
'should exist and have length 0'
,
function
()
{
assert
(
RSVP
.
Monitor
);
assert
.
equal
(
RSVP
.
Monitor
.
length
,
0
);
});
it
(
'should be a constructor'
,
function
()
{
var
monitor
=
new
RSVP
.
Monitor
();
assert
.
equal
(
Object
.
getPrototypeOf
(
monitor
),
RSVP
.
Monitor
.
prototype
,
'[[Prototype]] equals Monitor.prototype'
);
assert
.
equal
(
monitor
.
constructor
,
RSVP
.
Monitor
,
'constructor property of instances is set correctly'
);
assert
.
equal
(
RSVP
.
Monitor
.
prototype
.
constructor
,
RSVP
.
Monitor
,
'constructor property of prototype is set correctly'
);
});
it
(
'should return a new promise'
,
function
()
{
var
promise
=
new
RSVP
.
Monitor
();
assert
(
promise
instanceof
RSVP
.
Monitor
);
assert
(
promise
instanceof
RSVP
.
Promise
);
});
it
(
'should work without `new`'
,
function
()
{
var
promise
=
RSVP
.
Monitor
();
assert
(
promise
instanceof
RSVP
.
Monitor
);
assert
(
promise
instanceof
RSVP
.
Promise
);
});
});
describe
(
"`monitor`"
,
function
()
{
it
(
'should be a function'
,
function
()
{
var
monitor
=
new
RSVP
.
Monitor
();
assert
.
equal
(
typeof
monitor
.
monitor
,
"function"
);
});
it
(
'should return the same monitor instance'
,
function
()
{
var
monitor
=
new
RSVP
.
Monitor
(),
result
=
monitor
.
monitor
();
assert
.
equal
(
result
,
monitor
);
});
it
(
'should throw if the monitor is rejected'
,
function
(
done
)
{
var
monitor
=
new
RSVP
.
Monitor
();
monitor
.
cancel
();
setTimeout
(
function
()
{
assert
.
throws
(
function
()
{
monitor
.
monitor
();
},
RSVP
.
ResolvedMonitorError
);
done
();
},
20
);
});
});
describe
(
"`Monitor` instance"
,
function
()
{
it
(
'should not be rejected without any call'
,
function
(
done
)
{
var
monitor
=
new
RSVP
.
Monitor
();
setTimeout
(
function
()
{
assert
.
equal
(
monitor
.
isRejected
,
undefined
);
done
();
},
20
);
});
it
(
'a fulfillment does not impact the monitoring'
,
function
(
done
)
{
var
monitor
=
new
RSVP
.
Monitor
();
monitor
.
monitor
(
"ok"
);
setTimeout
(
function
()
{
assert
.
equal
(
monitor
.
isFulfilled
,
undefined
);
assert
.
equal
(
monitor
.
isRejected
,
undefined
);
done
();
},
20
);
});
it
(
'should be rejected if one entry is rejected'
,
function
(
done
)
{
var
monitor
=
new
RSVP
.
Monitor
();
monitor
.
monitor
(
RSVP
.
timeout
(
30
));
setTimeout
(
function
()
{
assert
.
equal
(
monitor
.
isRejected
,
undefined
);
setTimeout
(
function
()
{
assert
.
equal
(
monitor
.
isRejected
,
true
);
done
();
},
20
);
},
20
);
});
it
(
'get the rejectedReason from the rejected entry'
,
function
(
done
)
{
var
monitor
=
new
RSVP
.
Monitor
();
monitor
.
monitor
(
RSVP
.
timeout
(
1
));
setTimeout
(
function
()
{
assert
.
equal
(
monitor
.
isRejected
,
true
);
assert
.
equal
(
monitor
.
rejectedReason
,
"Timed out after 1 ms"
);
done
();
},
20
);
});
it
(
'reject cancels the remaining promise'
,
function
(
done
)
{
var
monitor
=
new
RSVP
.
Monitor
(),
pushed_result
=
RSVP
.
delay
(
1000
);
monitor
.
monitor
(
RSVP
.
timeout
(
1
));
monitor
.
monitor
(
pushed_result
);
setTimeout
(
function
()
{
assert
.
equal
(
monitor
.
isRejected
,
true
);
assert
.
equal
(
monitor
.
rejectedReason
,
"Timed out after 1 ms"
);
assert
.
equal
(
pushed_result
.
isRejected
,
true
);
assert
.
equal
(
pushed_result
.
rejectedReason
,
"cancel: Default Message"
);
done
();
},
20
);
});
it
(
'cancel also cancels the remaining promise'
,
function
(
done
)
{
var
monitor
=
new
RSVP
.
Monitor
(),
pushed_result
=
RSVP
.
delay
(
1000
);
monitor
.
monitor
(
pushed_result
);
monitor
.
cancel
();
setTimeout
(
function
()
{
assert
.
equal
(
monitor
.
isRejected
,
true
);
assert
(
monitor
.
rejectedReason
instanceof
RSVP
.
CancellationError
);
assert
.
equal
(
pushed_result
.
isRejected
,
true
);
assert
.
equal
(
pushed_result
.
rejectedReason
,
"cancel: Default Message"
);
done
();
},
20
);
});
// it("notify should be propagated until `then`", function (done) {
// var monitor = new RSVP.Monitor(), responses = [];
//
// monitor.then(null, null, function (notification) {
// responses.push(notification);
// });
//
// monitor.monitor(
// new RSVP.Promise(function (resolve, reject, progress) {
// progress("hello");
// })
// );
//
// setTimeout(function () {
// assert.equal(responses[0], "hello");
// done();
// }, 20);
// });
});
});