Comparing version 0.4.0 to 0.4.1
103
lib/utils.js
@@ -0,1 +1,6 @@ | ||
/* | ||
Yaku v0.4.1 | ||
(c) 2015 Yad Smood. http://ysmood.org | ||
License MIT | ||
*/ | ||
var Promise, isArray, isFunction, isNumber, utils, | ||
@@ -107,5 +112,2 @@ slice = [].slice; | ||
} | ||
if (utils.end == null) { | ||
utils.end = {}; | ||
} | ||
tryIter = function() { | ||
@@ -191,3 +193,3 @@ var e; | ||
args = [cb]; | ||
cb === null; | ||
cb = null; | ||
} | ||
@@ -221,4 +223,7 @@ return fn.apply(self, args).then(function(val) { | ||
* The end symbol. | ||
* @return {Promise} A promise that will end the current pipeline. | ||
*/ | ||
end: {}, | ||
end: function() { | ||
return new Promise(function() {}); | ||
}, | ||
@@ -314,5 +319,2 @@ /** | ||
} | ||
if (utils.end == null) { | ||
utils.end = {}; | ||
} | ||
run = function(preFn) { | ||
@@ -402,2 +404,87 @@ return preFn.then(function(val) { | ||
/** | ||
* Create a composable event source function. | ||
* Promise can't resolve multiple times, this function makes it possible, so | ||
* that you can easily map, filter and debounce events in a promise way. | ||
* @return {Function} `((value) ->, (reason) ->) -> source` The fucntion's | ||
* members: | ||
* ```js | ||
* { | ||
* emit: function (value) {}, | ||
* error: function (reason) {}, | ||
* handlers: Array | ||
* } | ||
* ``` | ||
* @example | ||
* ```js | ||
* var linear = utils.source(); | ||
* | ||
* var x = 0; | ||
* setInterval(() => { | ||
* linear.emit(x++); | ||
* }, 1000); | ||
* | ||
* // Wait for a moment then emit the value. | ||
* var quad = linear(x => utils.sleep(2000, x * x)); | ||
* | ||
* quad( | ||
* value => { console.log(value); }, | ||
* reason => { console.error(reason); } | ||
* ); | ||
* | ||
* // Dispose all children. | ||
* linear.handlers = []; | ||
* ``` | ||
* @example | ||
* ```js | ||
* var filter = fn => v => fn(v) ? v : utils.end(); | ||
* | ||
* var keyup = utils.source((emit) => { | ||
* document.querySelector('input').onkeyup = emit; | ||
* }); | ||
* | ||
* var keyupText = keyup(e => e.target.value); | ||
* | ||
* // Now we only get the input when the text length is greater than 3. | ||
* var keyupTextGT3 = keyupText(filter(text => text.length > 3)); | ||
* | ||
* keyupTextGT3(v => console.log(v)); | ||
* ``` | ||
*/ | ||
source: function(executor) { | ||
var src; | ||
src = function(onEmit, onError) { | ||
var nSrc; | ||
nSrc = utils.source(); | ||
src.handlers.push({ | ||
onEmit: onEmit, | ||
onError: onError, | ||
nEmit: nSrc.emit, | ||
nError: nSrc.error | ||
}); | ||
return nSrc; | ||
}; | ||
src.emit = function(val) { | ||
var handler, j, len, ref; | ||
ref = src.handlers; | ||
for (j = 0, len = ref.length; j < len; j++) { | ||
handler = ref[j]; | ||
Promise.resolve(val).then(handler.onEmit, handler.onError).then(handler.nEmit, handler.nError); | ||
} | ||
}; | ||
src.error = function(reason) { | ||
var handler, j, len, ref; | ||
ref = src.handlers; | ||
for (j = 0, len = ref.length; j < len; j++) { | ||
handler = ref[j]; | ||
Promise.reject(reason)["catch"](handler.onError).then(handler.nEmit, handler.nError); | ||
} | ||
}; | ||
src.handlers = []; | ||
if (typeof executor === "function") { | ||
executor(src.emit, src.error); | ||
} | ||
return src; | ||
}, | ||
/** | ||
* Throw an error to break the program. | ||
@@ -404,0 +491,0 @@ * @param {Any} err |
/* | ||
Yaku v0.4.0 | ||
Yaku v0.4.1 | ||
(c) 2015 Yad Smood. http://ysmood.org | ||
@@ -37,16 +37,10 @@ License MIT | ||
* var p = new Promise(function (resolve, reject) { | ||
* this.abort = function () { | ||
* var tmr = setTimeout(resolve, 3000); | ||
* this.abort = function (reason) { | ||
* clearTimeout(tmr); | ||
* reject(new Error('abort promise')); | ||
* reject(reason); | ||
* }; | ||
* | ||
* var tmr = setTimeout(function () { | ||
* if (Math.random() > 0.5) | ||
* resolve('ok'); | ||
* else | ||
* reject('no'); | ||
* }, 3000); | ||
* }); | ||
* | ||
* p.abort(); | ||
* p.abort(new Error('abort')); | ||
* ``` | ||
@@ -325,2 +319,8 @@ * @example | ||
* ``` | ||
* @example | ||
* You can even use sync resolution if you really know what you are doing. | ||
* ```js | ||
* var Promise = require('yaku'); | ||
* Promise.nextTick = function (fn) { fn() }; | ||
* ``` | ||
*/ | ||
@@ -327,0 +327,0 @@ Yaku.nextTick = root.process ? |
{ | ||
"name": "yaku", | ||
"version": "0.4.0", | ||
"version": "0.4.1", | ||
"description": "An ES6 Promises/A+ implementation that doesn't hurt.", | ||
@@ -42,2 +42,3 @@ "main": "lib/yaku.js", | ||
"bluebird": "2.9.34", | ||
"coffee-loader": "^0.7.2", | ||
"coffee-script": "1.9.3", | ||
@@ -50,3 +51,4 @@ "coffeelint": "1.10.1", | ||
"q": "1.4.1", | ||
"uglify-js": "2.4.23" | ||
"uglify-js": "2.4.23", | ||
"webpack": "1.11.0" | ||
}, | ||
@@ -53,0 +55,0 @@ "eslintConfig": { |
140
readme.md
@@ -9,3 +9,3 @@ <a href="http://promisesaplus.com/"> | ||
Yaku is full compatible with ES6's native [Promise][native], but much faster, and more error friendly. | ||
If you want to learn how Promise works, read the minimum implementation [docs/minPromiseA+.coffee][]. Without comments, it is only 80 lines of code (gzip size is 0.5KB). | ||
If you want to learn how Promise works, read the minimum implementation [docs/minPromiseA+.coffee][]. Without comments, it is only 80 lines of code (gzipped size is 0.5KB). | ||
It only implements the `constructor` and `then`. It passed all the tests of [promises-aplus-tests][]. | ||
@@ -21,7 +21,7 @@ | ||
- The minified file is only 3.2KB ([Bluebird][] / 73KB, [ES6-promise][] / 18KB) | ||
- 100% compliant with Promises/A+ specs | ||
- Better performance than the native Promise | ||
- The minified file is only 3.2KB ([Bluebird][] / 73KB, [ES6-promise][] / 18KB), 1.5KB gzipped | ||
- [Better "possibly unhandled rejection" and "long stack trace"][docs/debugHelperComparison.md] than [Bluebird][] | ||
- Much better performance than the native Promise | ||
- 100% compliant with Promises/A+ specs and ES6 | ||
- Designed to work on IE5+ and other major browsers | ||
- [Better][docs/debugHelperComparison.md] `possibly unhandled rejection` and `long stack trace` than [Bluebird][] | ||
- Well commented source code with every Promises/A+ spec | ||
@@ -45,3 +45,3 @@ | ||
Use something like [Browserify][] or [Webpack][], or download the `yaku.js` file from [release page][]. | ||
It supports both `AMD` and `CMD`. Raw usage without `AMD` or `CMD`: | ||
It supports both `AMD`, `CMD` and `CommonJS`. Raw usage without `AMD`, `CMD` or `CommonJS`: | ||
@@ -80,7 +80,2 @@ ```html | ||
- Better long stack trace support? | ||
> Latest Node.js and browsers are already support it. If you enabled it, Yaku will take advantage of it | ||
> without much overhead. Such as this library [longjohn][] for Node.js, or this article for [Chrome][crhome-lst]. | ||
- `catch` on old brwoser (IE7, IE8 etc)? | ||
@@ -95,6 +90,6 @@ | ||
- Why use [CoffeeScript][], not Javascript? | ||
- Better long stack trace support? | ||
> If it is really a problemn for people to use it, I will take time to translate it to JS. | ||
> Else, I'd like to keep the code as simple as CoffeeScript. | ||
> Latest Node.js and browsers are already support it. If you enabled it, Yaku will take advantage of it | ||
> without much overhead. Such as this library [longjohn][] for Node.js, or this article for [Chrome][crhome-lst]. | ||
@@ -107,3 +102,3 @@ - The name Yaku is weird? | ||
- ### **[Yaku(executor)](src/yaku.js?source#L76)** | ||
- ### **[Yaku(executor)](src/yaku.js?source#L70)** | ||
@@ -129,16 +124,10 @@ This class follows the [Promises/A+](https://promisesaplus.com) and | ||
var p = new Promise(function (resolve, reject) { | ||
this.abort = function () { | ||
var tmr = setTimeout(resolve, 3000); | ||
this.abort = function (reason) { | ||
clearTimeout(tmr); | ||
reject(new Error('abort promise')); | ||
reject(reason); | ||
}; | ||
var tmr = setTimeout(function () { | ||
if (Math.random() > 0.5) | ||
resolve('ok'); | ||
else | ||
reject('no'); | ||
}, 3000); | ||
}); | ||
p.abort(); | ||
p.abort(new Error('abort')); | ||
``` | ||
@@ -176,3 +165,3 @@ | ||
- ### **[then(onFulfilled, onRejected)](src/yaku.js?source#L111)** | ||
- ### **[then(onFulfilled, onRejected)](src/yaku.js?source#L105)** | ||
@@ -206,3 +195,3 @@ Appends fulfillment and rejection handlers to the promise, | ||
- ### **[catch(onRejected)](src/yaku.js?source#L131)** | ||
- ### **[catch(onRejected)](src/yaku.js?source#L125)** | ||
@@ -232,3 +221,3 @@ The `catch()` method returns a Promise and deals with rejected cases only. | ||
- ### **[Yaku.resolve(value)](src/yaku.js?source#L158)** | ||
- ### **[Yaku.resolve(value)](src/yaku.js?source#L152)** | ||
@@ -253,3 +242,3 @@ The `Promise.resolve(value)` method returns a Promise object that is resolved with the given value. | ||
- ### **[Yaku.reject(reason)](src/yaku.js?source#L172)** | ||
- ### **[Yaku.reject(reason)](src/yaku.js?source#L166)** | ||
@@ -271,3 +260,3 @@ The `Promise.reject(reason)` method returns a Promise object that is rejected with the given reason. | ||
- ### **[Yaku.race(iterable)](src/yaku.js?source#L196)** | ||
- ### **[Yaku.race(iterable)](src/yaku.js?source#L190)** | ||
@@ -301,3 +290,3 @@ The `Promise.race(iterable)` method returns a promise that resolves or rejects | ||
- ### **[Yaku.all(iterable)](src/yaku.js?source#L235)** | ||
- ### **[Yaku.all(iterable)](src/yaku.js?source#L229)** | ||
@@ -332,3 +321,3 @@ The `Promise.all(iterable)` method returns a promise that resolves when | ||
- ### **[Yaku.onUnhandledRejection(reason, p)](src/yaku.js?source#L284)** | ||
- ### **[Yaku.onUnhandledRejection(reason, p)](src/yaku.js?source#L278)** | ||
@@ -362,3 +351,3 @@ Catch all possibly unhandled rejections. If you want to use specific | ||
- ### **[Yaku.enableLongStackTrace](src/yaku.js?source#L303)** | ||
- ### **[Yaku.enableLongStackTrace](src/yaku.js?source#L297)** | ||
@@ -395,4 +384,12 @@ It is used to enable the long stack trace. | ||
- **<u>example</u>**: | ||
You can even use sync resolution if you really know what you are doing. | ||
```js | ||
var Promise = require('yaku'); | ||
Promise.nextTick = function (fn) { fn() }; | ||
``` | ||
# Utils | ||
@@ -473,3 +470,3 @@ | ||
- ### **[callbackify(fn, self)](src/utils.coffee?source#L151)** | ||
- ### **[callbackify(fn, self)](src/utils.coffee?source#L149)** | ||
@@ -487,12 +484,16 @@ If a function returns promise, convert it to | ||
- ### **[Deferred](src/utils.coffee?source#L173)** | ||
- ### **[Deferred](src/utils.coffee?source#L171)** | ||
Create a `jQuery.Deferred` like object. | ||
- ### **[end](src/utils.coffee?source#L185)** | ||
- ### **[end()](src/utils.coffee?source#L184)** | ||
The end symbol. | ||
- ### **[flow(fns)](src/utils.coffee?source#L247)** | ||
- **<u>return</u>**: { _Promise_ } | ||
A promise that will end the current pipeline. | ||
- ### **[flow(fns)](src/utils.coffee?source#L246)** | ||
Creates a function that is the composition of the provided functions. | ||
@@ -567,3 +568,3 @@ Besides, it can also accept async function that returns promise. | ||
- ### **[isPromise(obj)](src/utils.coffee?source#L290)** | ||
- ### **[isPromise(obj)](src/utils.coffee?source#L287)** | ||
@@ -576,3 +577,3 @@ Check if an object is a promise-like object. | ||
- ### **[promisify(fn, self)](src/utils.coffee?source#L319)** | ||
- ### **[promisify(fn, self)](src/utils.coffee?source#L316)** | ||
@@ -611,3 +612,3 @@ Convert a node callback style function to a function that returns | ||
- ### **[sleep(time, val)](src/utils.coffee?source#L338)** | ||
- ### **[sleep(time, val)](src/utils.coffee?source#L335)** | ||
@@ -626,4 +627,61 @@ Create a promise that will wait for a while before resolution. | ||
- ### **[throw(err)](src/utils.coffee?source#L353)** | ||
- ### **[source()](src/utils.coffee?source#L388)** | ||
Create a composable event source function. | ||
Promise can't resolve multiple times, this function makes it possible, so | ||
that you can easily map, filter and debounce events in a promise way. | ||
- **<u>return</u>**: { _Function_ } | ||
`((value) ->, (reason) ->) -> source` The fucntion's | ||
members: | ||
```js | ||
{ | ||
emit: function (value) {}, | ||
error: function (reason) {}, | ||
handlers: Array | ||
} | ||
``` | ||
- **<u>example</u>**: | ||
```js | ||
var linear = utils.source(); | ||
var x = 0; | ||
setInterval(() => { | ||
linear.emit(x++); | ||
}, 1000); | ||
// Wait for a moment then emit the value. | ||
var quad = linear(x => utils.sleep(2000, x * x)); | ||
quad( | ||
value => { console.log(value); }, | ||
reason => { console.error(reason); } | ||
); | ||
// Dispose all children. | ||
linear.handlers = []; | ||
``` | ||
- **<u>example</u>**: | ||
```js | ||
var filter = fn => v => fn(v) ? v : utils.end(); | ||
var keyup = utils.source((emit) => { | ||
document.querySelector('input').onkeyup = emit; | ||
}); | ||
var keyupText = keyup(e => e.target.value); | ||
// Now we only get the input when the text length is greater than 3. | ||
var keyupTextGT3 = keyupText(filter(text => text.length > 3)); | ||
keyupTextGT3(v => console.log(v)); | ||
``` | ||
- ### **[throw(err)](src/utils.coffee?source#L438)** | ||
Throw an error to break the program. | ||
@@ -630,0 +688,0 @@ |
58677
1137
712
11