Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
jio
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
18
Merge Requests
18
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
jio
Commits
3e152964
Commit
3e152964
authored
Sep 27, 2013
by
Tristan Cavelier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
promy replaced by RSVP library
parent
78fe0cd7
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
265 additions
and
1009 deletions
+265
-1009
Gruntfile.js
Gruntfile.js
+0
-10
src/jio/core/restCommandRejecter.js
src/jio/core/restCommandRejecter.js
+69
-0
src/jio/core/restCommandResolver.js
src/jio/core/restCommandResolver.js
+80
-0
src/jio/core/util.js
src/jio/core/util.js
+51
-38
src/jio/features/jobChecker.js
src/jio/features/jobChecker.js
+13
-11
src/jio/features/jobExecuter.js
src/jio/features/jobExecuter.js
+8
-21
src/jio/features/jobMaker.js
src/jio/features/jobMaker.js
+1
-1
src/jio/features/restApi.js
src/jio/features/restApi.js
+28
-16
src/jio/features/restParamChecker.js
src/jio/features/restParamChecker.js
+11
-11
src/jio/intro.js
src/jio/intro.js
+4
-4
src/promy/promy.js
src/promy/promy.js
+0
-897
No files found.
Gruntfile.js
View file @
3e152964
...
...
@@ -14,12 +14,6 @@ module.exports = function (grunt) {
errorsOnly
:
true
}
},
promy
:
{
src
:
[
'
src/promy/**/*.js
'
],
options
:
{
errorsOnly
:
true
}
},
jio
:
{
src
:
[
'
src/jio/**/*.js
'
],
exclude
:
[
'
src/jio/intro.js
'
,
'
src/jio/outro.js
'
],
...
...
@@ -84,10 +78,6 @@ module.exports = function (grunt) {
banner
:
'
/*! <%= pkg.name %> <%= pkg.version %>
'
+
'
<%= grunt.template.today("yyyy-mm-dd") %> */
\n
'
},
promy
:
{
src
:
'
src/promy/promy.js
'
,
dest
:
'
promy.min.js
'
},
jio
:
{
src
:
'
jio.js
'
,
// '<%= pkg.name %>.js'
dest
:
'
jio.min.js
'
...
...
src/jio/core/restCommandRejecter.js
0 → 100644
View file @
3e152964
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, regexp: true */
/*global constants, dictUpdate, deepClone */
function
restCommandRejecter
(
param
,
args
)
{
// reject(status, reason, message, {"custom": "value"});
// reject(status, reason, {..});
// reject(status, {..});
var
a
=
args
[
0
],
b
=
args
[
1
],
c
=
args
[
2
],
d
=
args
[
3
],
weak
,
strong
;
weak
=
{
"
result
"
:
"
error
"
};
strong
=
{};
weak
.
status
=
constants
.
http_status
.
unknown
;
weak
.
statusText
=
constants
.
http_status_text
.
unknown
;
weak
.
message
=
'
Command failed
'
;
weak
.
reason
=
'
fail
'
;
weak
.
method
=
param
.
method
;
if
(
param
.
kwargs
.
_id
)
{
weak
.
id
=
param
.
kwargs
.
_id
;
}
if
(
/Attachment$/
.
test
(
param
.
method
))
{
weak
.
attachment
=
param
.
kwargs
.
_attachment
;
}
if
(
typeof
a
!==
'
object
'
||
Array
.
isArray
(
a
))
{
strong
.
status
=
constants
.
http_status
[
a
];
strong
.
statusText
=
constants
.
http_status_text
[
a
];
if
(
strong
.
status
===
undefined
||
strong
.
statusText
===
undefined
)
{
return
restCommandRejecter
(
param
,
[
// can create infernal loop if 'internal_storage_error' is not defined
// in the constants
'
internal_storage_error
'
,
'
invalid response
'
,
'
Unknown status "
'
+
a
+
'
"
'
]);
}
a
=
b
;
b
=
c
;
c
=
d
;
}
if
(
typeof
a
!==
'
object
'
||
Array
.
isArray
(
a
))
{
strong
.
reason
=
a
;
a
=
b
;
b
=
c
;
}
if
(
typeof
a
!==
'
object
'
||
Array
.
isArray
(
a
))
{
strong
.
message
=
a
;
a
=
b
;
}
if
(
typeof
a
===
'
object
'
&&
!
Array
.
isArray
(
a
))
{
dictUpdate
(
weak
,
a
);
}
dictUpdate
(
weak
,
strong
);
strong
=
undefined
;
if
(
weak
.
error
===
undefined
)
{
weak
.
error
=
weak
.
statusText
.
toLowerCase
().
replace
(
/ /g
,
'
_
'
).
replace
(
/
[^
_a-z
]
/g
,
''
);
}
if
(
typeof
weak
.
message
!==
'
string
'
)
{
weak
.
message
=
""
;
}
if
(
typeof
weak
.
reason
!==
'
string
'
)
{
weak
.
reason
=
"
unknown
"
;
}
return
param
.
solver
.
reject
(
deepClone
(
weak
));
}
src/jio/core/
IODeferred
.js
→
src/jio/core/
restCommandResolver
.js
View file @
3e152964
/*jslint indent: 2, maxlen: 80,
nomen: true, sloppy: true, regexp
: true */
/*global
Deferred, inherits, constants, dictUpdate, deepClone, Blob
,
methodType
*/
/*jslint indent: 2, maxlen: 80,
sloppy: true, nomen
: true */
/*global
constants, methodType, dictUpdate, Blob, deepClone
,
restCommandRejecter
*/
function
IODeferred
(
method
,
info
)
{
IODeferred
.
super_
.
call
(
this
);
this
.
_info
=
info
||
{};
this
.
_method
=
method
;
// this._options = options;
}
inherits
(
IODeferred
,
Deferred
);
IODeferred
.
prototype
.
resolve
=
function
(
a
,
b
)
{
function
restCommandResolver
(
param
,
args
)
{
// resolve('ok', {"custom": "value"});
// resolve(200, {...});
// resolve({...});
var
weak
=
{
"
result
"
:
"
success
"
},
strong
=
{};
if
(
this
.
_
method
===
'
post
'
)
{
var
a
=
args
[
0
],
b
=
args
[
1
],
weak
=
{
"
result
"
:
"
success
"
},
strong
=
{};
if
(
param
.
method
===
'
post
'
)
{
weak
.
status
=
constants
.
http_status
.
created
;
weak
.
statusText
=
constants
.
http_status_text
.
created
;
}
else
if
(
methodType
(
this
.
_
method
)
===
"
writer
"
||
this
.
_
method
===
"
check
"
)
{
}
else
if
(
methodType
(
param
.
method
)
===
"
writer
"
||
param
.
method
===
"
check
"
)
{
weak
.
status
=
constants
.
http_status
.
no_content
;
weak
.
statusText
=
constants
.
http_status_text
.
no_content
;
}
else
{
weak
.
status
=
constants
.
http_status
.
ok
;
weak
.
statusText
=
constants
.
http_status_text
.
ok
;
}
if
(
this
.
_info
.
_id
)
{
weak
.
id
=
this
.
_info
.
_id
;
if
(
param
.
kwargs
.
_id
)
{
weak
.
id
=
param
.
kwargs
.
_id
;
}
if
(
/Attachment$/
.
test
(
this
.
_
method
))
{
weak
.
attachment
=
this
.
_info
.
_attachment
;
if
(
/Attachment$/
.
test
(
param
.
method
))
{
weak
.
attachment
=
param
.
kwargs
.
_attachment
;
}
weak
.
method
=
this
.
_
method
;
weak
.
method
=
param
.
method
;
if
(
typeof
a
===
'
string
'
||
(
typeof
a
===
'
number
'
&&
isFinite
(
a
)))
{
strong
.
status
=
constants
.
http_status
[
a
];
strong
.
statusText
=
constants
.
http_status_text
[
a
];
if
(
strong
.
status
===
undefined
||
strong
.
statusText
===
undefined
)
{
return
this
.
reject
(
return
restCommandRejecter
(
param
,
[
'
internal_storage_error
'
,
'
invalid response
'
,
'
Unknown status "
'
+
a
+
'
"
'
);
]
);
}
a
=
b
;
}
...
...
@@ -52,14 +44,14 @@ IODeferred.prototype.resolve = function (a, b) {
}
dictUpdate
(
weak
,
strong
);
strong
=
undefined
;
// free memory
if
(
this
.
_
method
===
'
post
'
&&
(
typeof
weak
.
id
!==
'
string
'
||
!
weak
.
id
))
{
return
this
.
reject
(
if
(
param
.
method
===
'
post
'
&&
(
typeof
weak
.
id
!==
'
string
'
||
!
weak
.
id
))
{
return
restCommandRejecter
(
param
,
[
'
internal_storage_error
'
,
'
invalid response
'
,
'
New document id have to be specified
'
);
]
);
}
if
(
this
.
_
method
===
'
getAttachment
'
)
{
if
(
param
.
method
===
'
getAttachment
'
)
{
if
(
typeof
weak
.
data
===
'
string
'
)
{
weak
.
data
=
new
Blob
([
weak
.
data
],
{
"
type
"
:
weak
.
content_type
||
weak
.
mimetype
||
""
...
...
@@ -68,111 +60,21 @@ IODeferred.prototype.resolve = function (a, b) {
delete
weak
.
mimetype
;
}
if
(
!
(
weak
.
data
instanceof
Blob
))
{
return
this
.
reject
(
return
restCommandRejecter
(
param
,
[
'
internal_storage_error
'
,
'
invalid response
'
,
'
getAttachment method needs a Blob as returned "data".
'
);
]
);
}
}
else
if
(
methodType
(
this
.
_
method
)
===
'
reader
'
&&
this
.
_
method
!==
'
check
'
&&
}
else
if
(
methodType
(
param
.
method
)
===
'
reader
'
&&
param
.
method
!==
'
check
'
&&
(
typeof
weak
.
data
!==
'
object
'
||
Object
.
getPrototypeOf
(
weak
.
data
)
!==
Object
.
prototype
))
{
return
this
.
reject
(
return
restCommandRejecter
(
param
,
[
'
internal_storage_error
'
,
'
invalid response
'
,
this
.
_method
+
'
method needs a dict as returned "data".
'
);
}
//return super_resolve(deepClone(weak));
return
IODeferred
.
super_
.
prototype
.
resolve
.
call
(
this
,
deepClone
(
weak
));
};
IODeferred
.
prototype
.
reject
=
function
(
a
,
b
,
c
,
d
)
{
// reject(status, reason, message, {"custom": "value"});
// reject(status, reason, {..});
// reject(status, {..});
var
weak
=
{
"
result
"
:
"
error
"
},
strong
=
{};
weak
.
status
=
constants
.
http_status
.
unknown
;
weak
.
statusText
=
constants
.
http_status_text
.
unknown
;
weak
.
message
=
'
Command failed
'
;
weak
.
reason
=
'
fail
'
;
weak
.
method
=
this
.
_method
;
if
(
this
.
_info
.
_id
)
{
weak
.
id
=
this
.
_info
.
_id
;
}
if
(
/Attachment$/
.
test
(
this
.
_method
))
{
weak
.
attachment
=
this
.
_info
.
_attachment
;
}
if
(
typeof
a
!==
'
object
'
||
Array
.
isArray
(
a
))
{
strong
.
status
=
constants
.
http_status
[
a
];
strong
.
statusText
=
constants
.
http_status_text
[
a
];
if
(
strong
.
status
===
undefined
||
strong
.
statusText
===
undefined
)
{
return
this
.
reject
(
// can create infernal loop if 'internal_storage_error' is not defined
// in the constants
'
internal_storage_error
'
,
'
invalid response
'
,
'
Unknown status "
'
+
a
+
'
"
'
);
}
a
=
b
;
b
=
c
;
c
=
d
;
}
if
(
typeof
a
!==
'
object
'
||
Array
.
isArray
(
a
))
{
strong
.
reason
=
a
;
a
=
b
;
b
=
c
;
}
if
(
typeof
a
!==
'
object
'
||
Array
.
isArray
(
a
))
{
strong
.
message
=
a
;
a
=
b
;
}
if
(
typeof
a
===
'
object
'
&&
!
Array
.
isArray
(
a
))
{
dictUpdate
(
weak
,
a
);
param
.
method
+
'
method needs a dict as returned "data".
'
]);
}
dictUpdate
(
weak
,
strong
);
strong
=
undefined
;
if
(
weak
.
error
===
undefined
)
{
weak
.
error
=
weak
.
statusText
.
toLowerCase
().
replace
(
/ /g
,
'
_
'
).
replace
(
/
[^
_a-z
]
/g
,
''
);
}
if
(
typeof
weak
.
message
!==
'
string
'
)
{
weak
.
message
=
""
;
}
if
(
typeof
weak
.
reason
!==
'
string
'
)
{
weak
.
reason
=
"
unknown
"
;
}
//return super_reject(deepClone(weak));
return
IODeferred
.
super_
.
prototype
.
reject
.
call
(
this
,
deepClone
(
weak
));
};
IODeferred
.
createFromDeferred
=
function
(
method
,
info
,
options
,
deferred
)
{
var
iodeferred
=
new
IODeferred
(
method
,
info
,
options
);
// iodeferred.promise().done(deferred.resolve.bind(deferred)).
// fail(deferred.reject.bind(deferred)).
// progress(deferred.notify.bind(deferred));
// // phantomjs doesn't like 'bind'...
iodeferred
.
promise
.
then
(
deferred
.
resolve
.
bind
(
deferred
),
deferred
.
reject
.
bind
(
deferred
),
deferred
.
notify
.
bind
(
deferred
)
);
return
iodeferred
;
};
IODeferred
.
createFromParam
=
function
(
param
)
{
return
IODeferred
.
createFromDeferred
(
param
.
method
,
param
.
kwargs
,
param
.
options
,
param
.
deferred
);
};
return
param
.
solver
.
resolve
(
deepClone
(
weak
));
}
src/jio/core/util.js
View file @
3e152964
/*jslint indent: 2, maxlen: 80, nomen: true, sloppy: true */
/*global exports, Blob, FileReader,
Deferred
, hex_sha256, XMLHttpRequest,
/*global exports, Blob, FileReader,
RSVP
, hex_sha256, XMLHttpRequest,
constants */
/**
...
...
@@ -310,32 +310,41 @@ function makeBinaryStringDigest(string) {
exports
.
util
.
makeBinaryStringDigest
=
makeBinaryStringDigest
;
function
readBlobAsBinaryString
(
blob
)
{
var
deferred
=
new
Deferred
(),
fr
=
new
FileReader
();
fr
.
addEventListener
(
"
load
"
,
deferred
.
resolve
.
bind
(
deferred
));
fr
.
addEventListener
(
"
error
"
,
deferred
.
reject
.
bind
(
deferred
));
fr
.
addEventListener
(
"
progress
"
,
deferred
.
notify
.
bind
(
deferred
));
var
fr
=
new
FileReader
();
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
,
notify
)
{
fr
.
addEventListener
(
"
load
"
,
resolve
);
fr
.
addEventListener
(
"
error
"
,
reject
);
fr
.
addEventListener
(
"
progress
"
,
notify
);
fr
.
readAsBinaryString
(
blob
);
return
deferred
.
promise
;
},
function
()
{
fr
.
abort
();
});
}
exports
.
util
.
readBlobAsBinaryString
=
readBlobAsBinaryString
;
function
readBlobAsArrayBuffer
(
blob
)
{
var
deferred
=
new
Deferred
(),
fr
=
new
FileReader
();
fr
.
addEventListener
(
"
load
"
,
deferred
.
resolve
.
bind
(
deferred
));
fr
.
addEventListener
(
"
error
"
,
deferred
.
reject
.
bind
(
deferred
));
fr
.
addEventListener
(
"
progress
"
,
deferred
.
notify
.
bind
(
deferred
));
var
fr
=
new
FileReader
();
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
,
notify
)
{
fr
.
addEventListener
(
"
load
"
,
resolve
);
fr
.
addEventListener
(
"
error
"
,
reject
);
fr
.
addEventListener
(
"
progress
"
,
notify
);
fr
.
readAsArrayBuffer
(
blob
);
return
deferred
.
promise
;
},
function
()
{
fr
.
abort
();
});
}
exports
.
util
.
readBlobAsArrayBuffer
=
readBlobAsArrayBuffer
;
function
readBlobAsText
(
blob
)
{
var
deferred
=
new
Deferred
(),
fr
=
new
FileReader
();
fr
.
addEventListener
(
"
load
"
,
deferred
.
resolve
.
bind
(
deferred
));
fr
.
addEventListener
(
"
error
"
,
deferred
.
reject
.
bind
(
deferred
));
fr
.
addEventListener
(
"
progress
"
,
deferred
.
notify
.
bind
(
deferred
));
var
fr
=
new
FileReader
();
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
,
notify
)
{
fr
.
addEventListener
(
"
load
"
,
resolve
);
fr
.
addEventListener
(
"
error
"
,
reject
);
fr
.
addEventListener
(
"
progress
"
,
notify
);
fr
.
readAsText
(
blob
);
return
deferred
.
promise
;
},
function
()
{
fr
.
abort
();
});
}
exports
.
util
.
readBlobAsText
=
readBlobAsText
;
...
...
@@ -355,7 +364,9 @@ exports.util.readBlobAsText = readBlobAsText;
* @return {Promise} The promise
*/
function
ajax
(
param
)
{
var
k
,
xhr
=
new
XMLHttpRequest
(),
deferred
=
new
Deferred
();
var
xhr
=
new
XMLHttpRequest
();
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
,
notify
)
{
var
k
;
xhr
.
open
(
param
.
type
||
"
GET
"
,
param
.
url
,
true
);
xhr
.
responseType
=
param
.
dataType
||
""
;
if
(
typeof
param
.
headers
===
'
object
'
&&
param
.
headers
!==
null
)
{
...
...
@@ -367,17 +378,19 @@ function ajax(param) {
}
xhr
.
addEventListener
(
"
load
"
,
function
(
e
)
{
if
(
e
.
target
.
status
>=
400
)
{
return
deferred
.
reject
(
e
);
return
reject
(
e
);
}
deferred
.
resolve
(
e
);
resolve
(
e
);
});
xhr
.
addEventListener
(
"
error
"
,
deferred
.
reject
.
bind
(
deferred
)
);
xhr
.
addEventListener
(
"
progress
"
,
deferred
.
notify
.
bind
(
deferred
)
);
xhr
.
addEventListener
(
"
error
"
,
reject
);
xhr
.
addEventListener
(
"
progress
"
,
notify
);
if
(
typeof
param
.
beforeSend
===
'
function
'
)
{
param
.
beforeSend
(
xhr
);
}
xhr
.
send
(
param
.
data
);
return
deferred
.
promise
;
},
function
()
{
xhr
.
abort
();
});
}
exports
.
util
.
ajax
=
ajax
;
...
...
src/jio/features/jobChecker.js
View file @
3e152964
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, unparam: true */
/*global arrayInsert, indexOf, deepClone, defaults,
IODeferred
*/
/*global arrayInsert, indexOf, deepClone, defaults,
restCommandRejecter
*/
// creates
// - some defaults job rule actions
...
...
@@ -8,11 +8,12 @@ function enableJobChecker(jio, shared, options) {
// dependencies
// - shared.jobs Object Array
// - param.promise Object
// creates
// - shared.job_rules Array
// uses 'job' event
s
// uses 'job' event
var
i
;
...
...
@@ -20,24 +21,25 @@ function enableJobChecker(jio, shared, options) {
shared
.
job_rule_actions
=
{
wait
:
function
(
original_job
,
new_job
)
{
original_job
.
deferred
.
promise
.
always
(
function
()
{
original_job
.
promise
.
always
(
function
()
{
shared
.
emit
(
'
job
'
,
new_job
);
});
new_job
.
state
=
'
waiting
'
;
new_job
.
modified
=
new
Date
();
},
update
:
function
(
original_job
,
new_job
)
{
if
(
!
new_job
.
deferred
)
{
if
(
!
new_job
.
solver
)
{
// promise associated to the job
new_job
.
state
=
'
done
'
;
shared
.
emit
(
'
jobDone
'
,
new_job
);
}
else
{
if
(
!
original_job
.
deferred
)
{
original_job
.
deferred
=
new_job
.
deferred
;
if
(
!
original_job
.
solver
)
{
original_job
.
solver
=
new_job
.
solver
;
}
else
{
original_job
.
deferred
.
promise
.
done
(
new_job
.
command
.
resolve
).
fail
(
new_job
.
command
.
reject
);
original_job
.
promise
.
then
(
new_job
.
command
.
resolve
,
new_job
.
command
.
reject
);
}
}
new_job
.
state
=
'
running
'
;
...
...
@@ -46,11 +48,11 @@ function enableJobChecker(jio, shared, options) {
deny
:
function
(
original_job
,
new_job
)
{
new_job
.
state
=
'
fail
'
;
new_job
.
modified
=
new
Date
();
IODeferred
.
createFromParam
(
new_job
).
reject
(
restCommandRejecter
(
new_job
,
[
'
precondition_failed
'
,
'
command denied
'
,
'
Command rejected by the job checker.
'
);
]
);
}
};
...
...
src/jio/features/jobExecuter.js
View file @
3e152964
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, unparam: true */
/*global setTimeout, Job, createStorage, deepClone, IODeferred, min */
/*global setTimeout, Job, createStorage, deepClone, min, restCommandResolver,
restCommandRejecter */
function
enableJobExecuter
(
jio
,
shared
)
{
// , options) {
...
...
@@ -46,44 +47,30 @@ function enableJobExecuter(jio, shared) { // , options) {
});
shared
.
on
(
'
jobDone
'
,
function
(
param
,
args
)
{
var
d
;
if
(
param
.
state
===
'
running
'
)
{
param
.
state
=
'
done
'
;
param
.
modified
=
new
Date
();
shared
.
emit
(
'
jobEnd
'
,
param
);
if
(
param
.
deferred
)
{
d
=
IODeferred
.
createFromDeferred
(
param
.
method
,
param
.
kwargs
,
param
.
options
,
param
.
deferred
);
d
.
resolve
.
apply
(
d
,
args
);
if
(
param
.
solver
)
{
restCommandResolver
(
param
,
args
);
}
}
});
shared
.
on
(
'
jobFail
'
,
function
(
param
,
args
)
{
var
d
;
if
(
param
.
state
===
'
running
'
)
{
param
.
state
=
'
fail
'
;
param
.
modified
=
new
Date
();
shared
.
emit
(
'
jobEnd
'
,
param
);
if
(
param
.
deferred
)
{
d
=
IODeferred
.
createFromDeferred
(
param
.
method
,
param
.
kwargs
,
param
.
options
,
param
.
deferred
);
d
.
reject
.
apply
(
d
,
args
);
if
(
param
.
solver
)
{
restCommandRejecter
(
param
,
args
);
}
}
});
shared
.
on
(
'
jobNotify
'
,
function
(
param
,
args
)
{
if
(
param
.
state
===
'
running
'
&&
param
.
deferred
)
{
param
.
deferred
.
notify
.
apply
(
param
.
deferred
,
args
);
if
(
param
.
state
===
'
running
'
&&
param
.
solver
)
{
param
.
solver
.
notify
(
args
[
0
]
);
}
});
}
src/jio/features/jobMaker.js
View file @
3e152964
...
...
@@ -58,7 +58,7 @@ function enableJobMaker(jio, shared, options) {
shared
.
rest_method_names
.
forEach
(
function
(
method
)
{
shared
.
on
(
method
,
function
(
param
)
{
if
(
param
.
deferred
)
{
if
(
param
.
solver
)
{
// params are good
shared
.
emit
(
'
job
'
,
param
);
}
...
...
src/jio/features/restApi.js
View file @
3e152964
/*jslint indent: 2, maxlen: 80, sloppy: true */
/*global arrayValuesToTypeDict, dictClear,
Deferred
, deepClone */
/*global arrayValuesToTypeDict, dictClear,
RSVP
, deepClone */
// adds methods to JIO
// - post
...
...
@@ -18,7 +18,12 @@
// - method string
// - kwargs object
// - options object
// - command object
// - solver object
// - solver.resolve function
// - solver.reject function
// - solver.notify function
// - cancellers object
// - promise object
function
enableRestAPI
(
jio
,
shared
)
{
// (jio, shared, options)
...
...
@@ -36,7 +41,7 @@ function enableRestAPI(jio, shared) { // (jio, shared, options)
];
function
prepareParamAndEmit
(
method
,
storage_spec
,
args
)
{
var
promise
,
callback
,
type_dict
,
param
=
{};
var
callback
,
type_dict
,
param
=
{};
type_dict
=
arrayValuesToTypeDict
(
Array
.
prototype
.
slice
.
call
(
args
));
type_dict
.
object
=
type_dict
.
object
||
[];
if
(
method
!==
'
allDocs
'
)
{
...
...
@@ -49,31 +54,38 @@ function enableRestAPI(jio, shared) { // (jio, shared, options)
}
else
{
param
.
kwargs
=
{};
}
param
.
solver
=
{};
param
.
options
=
deepClone
(
type_dict
.
object
.
shift
())
||
{};
//param.deferred = new IODeferred(method, param.kwargs, param.options);
param
.
deferred
=
new
Deferred
();
promise
=
param
.
deferred
.
promise
;
param
.
promise
=
new
RSVP
.
Promise
(
function
(
resolve
,
reject
,
notify
)
{
param
.
solver
.
resolve
=
resolve
;
param
.
solver
.
reject
=
reject
;
param
.
solver
.
notify
=
notify
;
},
function
()
{
var
k
;
for
(
k
in
param
.
cancellers
)
{
if
(
param
.
cancellers
.
hasOwnProperty
(
k
))
{
param
.
cancellers
[
k
]();
}
}
});
type_dict
[
'
function
'
]
=
type_dict
[
'
function
'
]
||
[];
if
(
type_dict
[
'
function
'
].
length
===
1
)
{
callback
=
type_dict
[
'
function
'
]
.
shift
()
;
p
romise
.
done
(
function
(
answer
)
{
callback
=
type_dict
[
'
function
'
]
[
0
]
;
p
aram
.
promise
.
then
(
function
(
answer
)
{
callback
(
undefined
,
answer
);
});
promise
.
fail
(
function
(
answer
)
{
},
function
(
answer
)
{
callback
(
answer
,
undefined
);
});
}
else
if
(
type_dict
[
'
function
'
].
length
>
1
)
{
promise
.
done
(
type_dict
[
'
function
'
].
shift
());
promise
.
fail
(
type_dict
[
'
function
'
].
shift
());
if
(
type_dict
[
'
function
'
].
length
===
1
)
{
promise
.
always
(
type_dict
[
'
function
'
].
shift
());
}
param
.
promise
.
then
(
type_dict
[
'
function
'
][
0
],
type_dict
[
'
function
'
][
1
],
type_dict
[
'
function
'
][
2
]);
}
type_dict
=
dictClear
(
type_dict
);
param
.
storage_spec
=
storage_spec
;
param
.
method
=
method
;
shared
.
emit
(
method
,
param
);
return
promise
;
return
p
aram
.
p
romise
;
}
shared
.
createRestApi
=
function
(
storage_spec
,
that
)
{
...
...
src/jio/features/restParamChecker.js
View file @
3e152964
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, unparam: true */
/*global Blob,
IODeferred
, Metadata */
/*global Blob,
restCommandRejecter
, Metadata */
function
enableRestParamChecker
(
jio
,
shared
)
{
// dependencies
// - param.
deferred
// - param.
solver
// - param.kwargs
// checks the kwargs and convert value if necessary
...
...
@@ -17,12 +17,12 @@ function enableRestParamChecker(jio, shared) {
function
checkId
(
param
)
{
if
(
typeof
param
.
kwargs
.
_id
!==
'
string
'
||
param
.
kwargs
.
_id
===
''
)
{
IODeferred
.
createFromParam
(
param
).
reject
(
restCommandRejecter
(
param
,
[
'
bad_request
'
,
'
wrong document id
'
,
'
Document id must be a non empty string.
'
);
delete
param
.
deferred
;
]
);
delete
param
.
solver
;
return
false
;
}
return
true
;
...
...
@@ -31,12 +31,12 @@ function enableRestParamChecker(jio, shared) {
function
checkAttachmentId
(
param
)
{
if
(
typeof
param
.
kwargs
.
_attachment
!==
'
string
'
||
param
.
kwargs
.
_attachment
===
''
)
{
IODeferred
.
createFromParam
(
param
).
reject
(
restCommandRejecter
(
param
,
[
'
bad_request
'
,
'
wrong attachment id
'
,
'
Attachment id must be a non empty string.
'
);
delete
param
.
deferred
;
]
);
delete
param
.
solver
;
return
false
;
}
return
true
;
...
...
@@ -84,15 +84,15 @@ function enableRestParamChecker(jio, shared) {
delete
param
.
kwargs
.
_mimetype
;
delete
param
.
kwargs
.
_content_type
;
}
else
{
IODeferred
.
createFromParam
(
param
).
reject
(
restCommandRejecter
(
param
,
[
'
bad_request
'
,
'
wrong attachment
'
,
'
Attachment information must be like {"_id": document id,
'
+
'
"_attachment": attachment name, "_data": string, ["_mimetype":
'
+
'
content type]} or {"_id": document id, "_attachment":
'
+
'
attachment name, "_blob": Blob}
'
);
delete
param
.
deferred
;
]
);
delete
param
.
solver
;
}
});
...
...
src/jio/intro.js
View file @
3e152964
...
...
@@ -4,11 +4,11 @@
return
define
(
dependencies
,
module
);
}
if
(
typeof
exports
===
'
object
'
)
{
return
module
(
exports
,
require
(
'
promy
'
),
require
(
'
sha256
'
));
return
module
(
exports
,
require
(
'
rsvp
'
),
require
(
'
sha256
'
));
}
window
.
jIO
=
{};
module
(
window
.
jIO
,
promy
,
{
hex_sha256
:
hex_sha256
});
}([
'
exports
'
,
'
promy
'
,
'
sha256
'
],
function
(
exports
,
promy
,
sha256
)
{
module
(
window
.
jIO
,
RSVP
,
{
hex_sha256
:
hex_sha256
});
}([
'
exports
'
,
'
rsvp
'
,
'
sha256
'
],
function
(
exports
,
RSVP
,
sha256
)
{
"
use strict
"
;
var
hex_sha256
=
sha256
.
hex_sha256
,
Deferred
=
promy
.
Deferred
;
var
hex_sha256
=
sha256
.
hex_sha256
;
src/promy/promy.js
deleted
100644 → 0
View file @
78fe0cd7
/*
* Promy: Promises library
* Copyright (C) 2013 Nexedi SA
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global setInterval, setTimeout, clearInterval, clearTimeout */
(
function
(
dependencies
,
module
)
{
"
use strict
"
;
/*global define, exports, window */
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
return
define
(
dependencies
,
module
);
}
if
(
typeof
exports
===
'
object
'
)
{
module
(
exports
);
}
if
(
typeof
window
===
'
object
'
)
{
window
.
promy
=
{};
module
(
window
.
promy
);
}
}([
'
exports
'
],
function
(
exports
)
{
"
use strict
"
;
var
UNRESOLVED
=
0
,
RESOLVED
=
1
,
REJECTED
=
2
,
CANCELLED
=
3
;
/**
* thenItem(item, [onSucess], [onError], [onProgress]): any
*
* Execute one of the given callback when the item is fulfilled. If the item
* is not a promise, then onSuccess is called with the item as first
* parameter.
*
* @param {Any} item A promise, deferred or a simple value
* @param {Function} [onSuccess] The callback to call on resolve
* @param {Function} [onError] The callback to call on reject
* @param {Function} [onProgress] The callback to call on notify
*/
function
thenItem
(
item
,
onSuccess
,
onError
,
onProgress
)
{
if
(
typeof
item
===
'
object
'
&&
item
!==
null
)
{
if
(
typeof
item
.
promise
===
'
object
'
&&
item
.
promise
!==
null
&&
typeof
item
.
promise
.
then
===
'
function
'
)
{
// item seams to be a Deferred
return
item
.
promise
.
then
(
onSuccess
,
onError
,
onProgress
);
}
if
(
typeof
item
.
then
===
'
function
'
)
{
// item seams to be a Promise
return
item
.
then
(
onSuccess
,
onError
,
onProgress
);
}
}
return
onSuccess
(
item
);
}
/**
* promiseResolve(promise, answers): any
*
* Resolve the promise with the given answers.
*
* @param {Promise} promise The promise to resolve
* @param {Array} answers The arguments to give
*/
function
promiseResolve
(
promise
,
answers
)
{
var
array
;
if
(
promise
.
_state
===
UNRESOLVED
)
{
promise
.
_state
=
RESOLVED
;
promise
.
_answers
=
answers
;
array
=
promise
.
_onResolve
.
slice
();
setTimeout
(
function
()
{
var
i
;
for
(
i
=
0
;
i
<
array
.
length
;
i
+=
1
)
{
try
{
array
[
i
].
apply
(
promise
,
promise
.
_answers
);
}
catch
(
ignore
)
{}
// errors will never be retrieved by global
}
});
// free the memory
promise
.
_onResolve
=
undefined
;
promise
.
_onReject
=
undefined
;
promise
.
_onProgress
=
undefined
;
}
}
/**
* promiseReject(promise, answers): any
*
* Reject the promise with the given answers.
*
* @param {Promise} promise The promise to reject
* @param {Array} answers The arguments to give
*/
function
promiseReject
(
promise
,
answers
)
{
var
array
;
if
(
promise
.
_state
===
UNRESOLVED
)
{
promise
.
_state
=
REJECTED
;
promise
.
_answers
=
answers
;
array
=
promise
.
_onReject
.
slice
();
setTimeout
(
function
()
{
var
i
;
for
(
i
=
0
;
i
<
array
.
length
;
i
+=
1
)
{
try
{
array
[
i
].
apply
(
promise
,
promise
.
_answers
);
}
catch
(
ignore
)
{}
// errors will never be retrieved by global
}
});
// free the memory
promise
.
_onResolve
=
undefined
;
promise
.
_onReject
=
undefined
;
promise
.
_onProgress
=
undefined
;
}
}
/**
* promiseNotify(promise, answers): any
*
* Notify the promise with the given answers.
*
* @param {Promise} promise The promise to notify
* @param {Array} answers The arguments to give
*/
function
promiseNotify
(
promise
,
answers
)
{
var
i
;
if
(
promise
.
_onProgress
)
{
for
(
i
=
0
;
i
<
promise
.
_onProgress
.
length
;
i
+=
1
)
{
try
{
promise
.
_onProgress
[
i
].
apply
(
promise
,
answers
);
}
catch
(
ignore
)
{}
// errors will never be retrieved by global
}
}
}
/**
* Promise(cancel)
*
* @class Promise
* @constructor
*/
function
Promise
(
cancel
)
{
this
.
_onReject
=
[];
this
.
_onResolve
=
[];
this
.
_onProgress
=
[];
this
.
_state
=
UNRESOLVED
;
if
(
typeof
cancel
===
'
function
'
)
{
this
.
_cancel
=
cancel
;
}
}
////////////////////////////////////////////////////////////
// http://wiki.commonjs.org/wiki/Promises/A
// then(fulfilledHandler, errorHandler, progressHandler)
/**
* then([onSuccess], [onError], [onProgress]): Promise
*
* Returns a new Promise with the return value of the `onSuccess` or `onError`
* callback as first parameter. If the pervious promise is resolved, the
* `onSuccess` callback is called. If rejected, the `onError` callback is
* called. If notified, `onProgress` is called.
*
* Deferred.when(1).
* then(function (one) { return one + 1; }).
* then(console.log); // shows 2
*
* @method then
* @param {Function} [onSuccess] The callback to call on resolve
* @param {Function} [onError] The callback to call on reject
* @param {Function} [onProgress] The callback to call on notify
* @return {Promise} The new promise
*/
Promise
.
prototype
.
then
=
function
(
onSuccess
,
onError
,
onProgress
)
{
/*global Deferred*/
var
defer
,
next
=
new
this
.
constructor
(
this
.
_cancel
),
that
=
this
;
defer
=
new
Deferred
();
defer
.
promise
=
next
;
switch
(
this
.
_state
)
{
case
RESOLVED
:
if
(
typeof
onSuccess
===
'
function
'
)
{
setTimeout
(
function
()
{
try
{
thenItem
(
onSuccess
.
apply
(
that
,
that
.
_answers
),
defer
.
resolve
.
bind
(
defer
),
defer
.
reject
.
bind
(
defer
)
);
}
catch
(
e
)
{
defer
.
reject
(
e
);
}
});
}
else
{
setTimeout
(
function
()
{
defer
.
resolve
.
apply
(
defer
,
that
.
_answers
);
});
}
break
;
case
REJECTED
:
if
(
typeof
onError
===
'
function
'
)
{
setTimeout
(
function
()
{
var
result
;
try
{
result
=
onError
.
apply
(
that
,
that
.
_answers
);
if
(
result
===
undefined
)
{
return
defer
.
reject
.
apply
(
defer
,
that
.
_answers
);
}
thenItem
(
result
,
defer
.
reject
.
bind
(
defer
),
defer
.
reject
.
bind
(
defer
)
);
}
catch
(
e
)
{
defer
.
reject
(
e
);
}
});
}
else
{
setTimeout
(
function
()
{
defer
.
reject
.
apply
(
defer
,
that
.
_answers
);
});
}
break
;
case
UNRESOLVED
:
if
(
typeof
onSuccess
===
'
function
'
)
{
this
.
_onResolve
.
push
(
function
()
{
try
{
thenItem
(
onSuccess
.
apply
(
that
,
arguments
),
defer
.
resolve
.
bind
(
defer
),
defer
.
reject
.
bind
(
defer
),
defer
.
notify
.
bind
(
defer
)
);
}
catch
(
e
)
{
defer
.
reject
(
e
);
}
});
}
else
{
this
.
_onResolve
.
push
(
function
()
{
defer
.
resolve
.
apply
(
defer
,
arguments
);
});
}
if
(
typeof
onError
===
'
function
'
)
{
this
.
_onReject
.
push
(
function
()
{
try
{
thenItem
(
onError
.
apply
(
that
,
that
.
_answers
),
defer
.
reject
.
bind
(
defer
),
defer
.
reject
.
bind
(
defer
)
);
}
catch
(
e
)
{
defer
.
reject
(
e
);
}
});
}
else
{
this
.
_onReject
.
push
(
function
()
{
defer
.
reject
.
apply
(
defer
,
that
.
_answers
);
});
}
if
(
typeof
onProgress
===
'
function
'
)
{
this
.
_onProgress
.
push
(
function
()
{
var
result
;
try
{
result
=
onProgress
.
apply
(
that
,
arguments
);
if
(
result
===
undefined
)
{
defer
.
notify
.
apply
(
defer
,
arguments
);
}
else
{
defer
.
notify
(
result
);
}
}
catch
(
e
)
{
defer
.
notify
.
apply
(
defer
,
arguments
);
}
});
}
else
{
this
.
_onProgress
.
push
(
function
()
{
defer
.
notify
.
apply
(
defer
,
arguments
);
});
}
break
;
default
:
break
;
}
return
next
;
};
// p.resolve() ?
// p.reject() ?
// p.notify() ?
/**
* p.cancel(): p
*
* Cancels the operation by calling promise._cancel().
*
* @method cancel
* @return {Promise} this
*/
Promise
.
prototype
.
cancel
=
function
()
{
if
(
this
.
_state
===
UNRESOLVED
)
{
this
.
_state
=
CANCELLED
;
if
(
typeof
this
.
_cancel
===
'
function
'
)
{
this
.
_cancel
();
}
this
.
_onResolve
=
undefined
;
this
.
_onReject
=
undefined
;
this
.
_onProgress
=
undefined
;
}
return
this
;
};
/**
* p.timeout(delay): p
*
* Reject the promise with an Error("Timeout") and cancel the operation.
*
* @method timeout
* @param {Number} delay The delay before rejection
* @return {Promise} this
*/
Promise
.
prototype
.
timeout
=
function
(
delay
)
{
return
exports
.
choose
(
this
,
exports
.
delay
(
delay
).
then
(
function
()
{
throw
new
Error
(
"
Timeout (
"
+
delay
+
"
)
"
);
}));
};
////////////////////////////////////////////////////////////
// http://wiki.commonjs.org/wiki/Promises/A
// get(propertyName)
/**
* get(property): Promise
*
* Get the property of the promise response as first parameter of the new
* Promise.
*
* Deferred.when({'a': 'b'}).get('a').then(console.log); // shows 'b'
*
* @method get
* @param {String} property The object property name
* @return {Promise} The promise
*/
Promise
.
prototype
.
get
=
function
(
property
)
{
return
this
.
then
(
function
(
dict
)
{
return
dict
[
property
];
});
};
////////////////////////////////////////////////////////////
// http://wiki.commonjs.org/wiki/Promises/A
// call(functionName, arg1, arg2, ...)
/**
* call(function_name, *args): Promise
*
* Deferred.when({'a': console.log}).call('a', 'b'); // shows 'b'
*
* @method call
* @param {String} function_name The function to call
* @param {Any} *[args] The function arguments
* @return {Promise} A new promise
*/
Promise
.
prototype
.
call
=
function
(
function_name
)
{
var
args
=
Array
.
prototype
.
slice
.
call
(
arguments
,
1
);
return
this
.
then
(
function
(
dict
)
{
return
dict
[
function_name
].
apply
(
dict
,
args
);
});
};
/**
* put(property, value): Promise
*
* Put a property value from a promise response and return the registered
* value as first parameter of the new Promise.
*
* Deferred.when({'a': 'b'}).put('a', 'c').then(console.log); // shows 'c'
*
* @method put
* @param {String} property The object property name
* @param {Any} value The value to put
* @return {Promise} A new promise
*/
Promise
.
prototype
.
put
=
function
(
property
,
value
)
{
return
this
.
then
(
function
(
dict
)
{
dict
[
property
]
=
value
;
return
dict
[
property
];
});
};
/**
* del(property): Promise
*
* Delete a property value from a promise response and return the property
* value as first parameter of the new Promise.
*
* Deferred.when({'a': 'b'}).del('a').then(console.log);
* // shows undefined
*
* @method del
* @param {String} property The object property name
* @return {Promise} A new promise
*/
Promise
.
prototype
.
del
=
function
(
property
)
{
return
this
.
then
(
function
(
dict
)
{
delete
dict
[
property
];
return
dict
[
property
];
});
};
/**
* p.done(callback): p
*
* Call the callback on resolve.
*
* Deferred.when(1).
* done(function (one) { return one + 1; }).
* done(console.log); // shows 1
*
* @method done
* @param {Function} callback The callback to call on resolve
* @return {Promise} This promise
*/
Promise
.
prototype
.
done
=
function
(
callback
)
{
var
that
=
this
;
if
(
typeof
callback
!==
'
function
'
)
{
return
this
;
}
switch
(
this
.
_state
)
{
case
RESOLVED
:
setTimeout
(
function
()
{
try
{
callback
.
apply
(
that
,
that
.
_answers
);
}
catch
(
ignore
)
{}
// errors will never be retrieved by global
});
break
;
case
UNRESOLVED
:
this
.
_onResolve
.
push
(
callback
);
break
;
default
:
break
;
}
return
this
;
};
/**
* p.fail(callback): p
*
* Call the callback on reject.
*
* promisedTypeError().
* fail(function (e) { name_error(); }).
* fail(console.log); // shows TypeError
*
* @method fail
* @param {Function} callback The callback to call on reject
* @return {Promise} This promise
*/
Promise
.
prototype
.
fail
=
function
(
callback
)
{
var
that
=
this
;
if
(
typeof
callback
!==
'
function
'
)
{
return
this
;
}
switch
(
this
.
_state
)
{
case
REJECTED
:
setTimeout
(
function
()
{
try
{
callback
.
apply
(
that
,
that
.
_answers
);
}
catch
(
ignore
)
{}
// errors will never be retrieved by global
});
break
;
case
UNRESOLVED
:
this
.
_onReject
.
push
(
callback
);
break
;
default
:
break
;
}
return
this
;
};
/**
* p.progress(callback): p
*
* Call the callback on notify.
*
* Promise.delay(100, 10).
* progress(function () { return null; }).
* progress(console.log); // does not show null
*
* @method progress
* @param {Function} callback The callback to call on notify
* @return {Promise} This promise
*/
Promise
.
prototype
.
progress
=
function
(
callback
)
{
if
(
typeof
callback
!==
'
function
'
)
{
return
this
;
}
switch
(
this
.
_state
)
{
case
UNRESOLVED
:
this
.
_onProgress
.
push
(
callback
);
break
;
default
:
break
;
}
return
this
;
};
/**
* p.always(callback): p
*
* Call the callback on resolve or on reject.
*
* sayHello().
* done(iAnswer).
* fail(iHeardNothing).
* always(iKeepWalkingAnyway);
*
* @method always
* @param {Function} callback The callback to call on resolve or on reject
* @return {Promise} This promise
*/
Promise
.
prototype
.
always
=
function
(
callback
)
{
var
that
=
this
;
if
(
typeof
callback
!==
'
function
'
)
{
return
this
;
}
switch
(
this
.
_state
)
{
case
RESOLVED
:
case
REJECTED
:
setTimeout
(
function
()
{
try
{
callback
.
apply
(
that
,
that
.
_answers
);
}
catch
(
ignore
)
{}
// errors will never be retrieved by global
});
break
;
case
UNRESOLVED
:
that
.
_onReject
.
push
(
callback
);
that
.
_onResolve
.
push
(
callback
);
break
;
default
:
break
;
}
return
this
;
};
exports
.
Promise
=
Promise
;
/**
* Deferred(cancel)
*
* @class Deferred
* @constructor
*/
function
Deferred
(
cancel
)
{
this
.
promise
=
new
Promise
(
cancel
);
}
/**
* resolve(*args): any
*
* Resolves the promise with the given arguments.
*
* @method resolve
* @param {Any} *[args] The arguments to give
*/
Deferred
.
prototype
.
resolve
=
function
()
{
return
promiseResolve
(
this
.
promise
,
arguments
);
};
/**
* reject(*args): any
*
* Rejects the promise with the given arguments.
*
* @method reject
* @param {Any} *[args] The arguments to give
*/
Deferred
.
prototype
.
reject
=
function
()
{
return
promiseReject
(
this
.
promise
,
arguments
);
};
/**
* notify(*args): any
*
* Notifies the promise with the given arguments.
*
* @method notify
* @param {Any} *[args] The arguments to give
*/
Deferred
.
prototype
.
notify
=
function
()
{
return
promiseNotify
(
this
.
promise
,
arguments
);
};
exports
.
Deferred
=
Deferred
;
//////////////////////////////////////////////////////////////////////
// Inspired by Task.js
/**
* now(value): Promise
*
* Converts an ordinary value into a fulfilled promise.
*
* @param {Any} value The value to use
* @return {Promise} The resolved promise
*/
exports
.
now
=
function
(
value
)
{
var
deferred
=
new
Deferred
();
deferred
.
resolve
(
value
);
return
deferred
.
promise
;
};
/**
* join(*promises): Promise
*
* Produces a promise that is resolved when all the given promises are
* resolved. The resolved value is an array of each of the resolved values of
* the given promises.
*
* If any of the promises is rejected, the joined promise is rejected with the
* same error, and any remaining unfulfilled promises are cancelled.
*
* @param {Promise} *[promises] The promises to join
* @return {Promise} A new promise
*/
exports
.
join
=
function
()
{
var
promises
,
results
=
[],
i
,
count
=
0
,
deferred
;
promises
=
Array
.
prototype
.
slice
.
call
(
arguments
);
function
cancel
()
{
var
j
;
for
(
j
=
0
;
j
<
promises
.
length
;
j
+=
1
)
{
if
(
typeof
promises
[
j
].
cancel
===
'
function
'
)
{
promises
[
j
].
cancel
();
}
}
}
deferred
=
new
Deferred
(
cancel
);
function
succeed
(
j
)
{
return
function
(
answer
)
{
results
[
j
]
=
answer
;
count
+=
1
;
if
(
count
!==
promises
.
length
)
{
return
;
}
deferred
.
resolve
(
results
);
};
}
function
failed
(
answer
)
{
cancel
();
deferred
.
reject
(
answer
);
}
function
notify
(
j
)
{
return
function
(
answer
)
{
deferred
.
notify
({
"
promise
"
:
this
,
"
index
"
:
j
,
"
answer
"
:
answer
});
};
}
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
promises
[
i
].
then
(
succeed
(
i
),
failed
,
notify
(
i
));
}
return
deferred
.
promise
;
};
/**
* choose(*promises): Promise
*
* Produces a promise that is fulfilled when any one of the given promises is
* fulfilled. As soon as one of the promises is fulfilled, whether by being
* resolved or rejected, all the other promises are cancelled.
*
* @param {Promise} *[promises] The promises to use
* @return {Promise} A new promise
*/
exports
.
choose
=
function
()
{
var
promises
,
i
,
deferred
;
promises
=
Array
.
prototype
.
slice
.
call
(
arguments
);
function
cancel
()
{
var
j
;
for
(
j
=
0
;
j
<
promises
.
length
;
j
+=
1
)
{
if
(
typeof
promises
[
j
].
cancel
===
'
function
'
)
{
promises
[
j
].
cancel
();
}
}
}
deferred
=
new
Deferred
(
cancel
);
function
succeed
(
answer
)
{
cancel
();
deferred
.
resolve
(
answer
);
}
function
failed
(
answer
)
{
cancel
();
deferred
.
reject
(
answer
);
}
function
notify
(
j
)
{
return
function
(
answer
)
{
deferred
.
notify
({
"
promise
"
:
this
,
"
index
"
:
j
,
"
answer
"
:
answer
});
};
}
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
promises
[
i
].
then
(
succeed
,
failed
,
notify
(
i
));
}
return
deferred
.
promise
;
};
/**
* never(): Promise
*
* Produces a promise that is never fulfilled.
*
* @return {Promise} A promise
*/
exports
.
never
=
function
()
{
return
new
Promise
();
};
/**
* sleep(delay[, every]): Promise
*
* Resolve the promise after `timeout` milliseconds and notfies us every
* `every` milliseconds.
*
* Deferred.delay(50, 10).then(console.log, console.error, console.log);
* // // shows
* // 10 // from progress
* // 20 // from progress
* // 30 // from progress
* // 40 // from progress
* // 50 // from progress
* // 50 // from success
*
* @param {Number} delay In milliseconds
* @param {Number} [every] In milliseconds
* @return {Promise} A new promise
*/
exports
.
sleep
=
function
(
delay
,
every
)
{
var
deferred
,
timeout
,
interval
,
now
=
0
;
function
cancel
()
{
clearTimeout
(
timeout
);
clearInterval
(
interval
);
}
deferred
=
new
Deferred
(
cancel
);
if
(
typeof
every
===
'
number
'
&&
isFinite
(
every
))
{
interval
=
setInterval
(
function
()
{
now
+=
every
;
deferred
.
notify
(
now
);
},
every
);
}
timeout
=
setTimeout
(
function
()
{
clearInterval
(
interval
);
deferred
.
notify
(
delay
);
deferred
.
resolve
(
delay
);
},
delay
);
return
deferred
.
promise
;
};
////////////////////////////////////////////////////////////
// http://wiki.commonjs.org/wiki/Promises/B
// when(value, callback, errback_opt)
/**
* when(item, [onSuccess], [onError], [onProgress]): Promise
*
* Return an item as first parameter of the promise answer. If item is of
* type Promise, the method will just return the promise. If item is of type
* Deferred, the method will return the deferred promise.
*
* Deferred.when('a').then(console.log); // shows 'a'
*
* @param {Any} item The item to use
* @param {Function} [onSuccess] The callback called on success
* @param {Function} [onError] the callback called on error
* @param {Function} [onProgress] the callback called on progress
* @return {Promise} The promise
*/
exports
.
when
=
function
(
item
,
onSuccess
,
onError
,
onProgress
)
{
if
(
typeof
item
===
'
object
'
&&
item
!==
null
)
{
if
(
typeof
item
.
promise
===
'
object
'
&&
item
.
promise
!==
null
&&
typeof
item
.
promise
.
then
===
'
function
'
)
{
// item seams to be a Deferred
return
item
.
promise
.
then
(
onSuccess
,
onError
,
onProgress
);
}
if
(
typeof
item
.
then
===
'
function
'
)
{
// item seams to be a Promise
return
item
.
then
(
onSuccess
,
onError
,
onProgress
);
}
}
// item is just a value, convert into fulfilled promise
var
deferred
=
new
Deferred
(),
promise
;
if
(
typeof
onSuccess
===
'
function
'
)
{
promise
=
deferred
.
promise
.
then
(
onSuccess
);
}
else
{
promise
=
deferred
.
promise
;
}
deferred
.
resolve
(
item
);
return
promise
;
};
////////////////////////////////////////////////////////////
// http://wiki.commonjs.org/wiki/Promises/B
// get(object, name)
/**
* get(dict, property): Promise
*
* Return the dict property as first parameter of the promise answer.
*
* Deferred.get({'a': 'b'}, 'a').then(console.log); // shows 'b'
*
* @param {Object} dict The object to use
* @param {String} property The object property name
* @return {Promise} The promise
*/
exports
.
get
=
function
(
dict
,
property
)
{
var
p
=
new
Deferred
();
try
{
p
.
resolve
(
dict
[
property
]);
}
catch
(
e
)
{
p
.
reject
(
e
);
}
return
p
;
};
////////////////////////////////////////////////////////////
// http://wiki.commonjs.org/wiki/Promises/B
// put(object, name, value)
/**
* put(dict, property, value): Promise
*
* Set and return the dict property as first parameter of the promise answer.
*
* Deferred.put({'a': 'b'}, 'a', 'c').then(console.log); // shows 'c'
*
* @param {Object} dict The object to use
* @param {String} property The object property name
* @param {Any} value The value
* @return {Promise} The promise
*/
exports
.
put
=
function
(
dict
,
property
,
value
)
{
var
p
=
new
Deferred
();
try
{
dict
[
property
]
=
value
;
p
.
resolve
(
dict
[
property
]);
}
catch
(
e
)
{
p
.
reject
(
e
);
}
return
p
;
};
////////////////////////////////////////////////////////////
// http://wiki.commonjs.org/wiki/Promises/B
// del(object, name)
/**
* del(dict, property): Promise
*
* Delete and return the dict property as first parameter of the promise
* answer.
*
* Deferred.del({'a': 'b'}, 'a').then(console.log); // shows undefined
*
* @param {Object} dict The object to use
* @param {String} property The object property name
* @return {Promise} The promise
*/
exports
.
del
=
function
(
dict
,
property
)
{
var
p
=
new
Deferred
();
try
{
delete
dict
[
property
];
p
.
resolve
(
dict
[
property
]);
}
catch
(
e
)
{
p
.
reject
(
e
);
}
return
p
;
};
}));
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment