Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fsjohnhuang/iPromise

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

76 Commits

Repository files navigation

iPromise v0.8.3

iPromise is a standalone async library which implements the Promises/A+. Async codes are confusing because you will dump into the callback hell easily. iPromise improves the readability of async codes by saving us from the hell.

###In This Documentation 1. Tutorial
2. API
Constructor
iPromise(mixin, arg)
Instance Methods
iPromise#then(fulfilledFn, rejectedFn, finallyFn)
iPromise#catch(rejectedFn, finallyFn)
iPromise#wait(ms)
Function Properties
iPromise.resolve(val)
iPromise.reject(reason)
iPromise.all(condition)
iPromise.any/race(condition)
iPromise.wait(ms, arg)
3. Changelog
4. Referrence

Tutorial

###1. Build your own production-ready code.

> git clone https://github.com/fsjohnhuang/iPromise.git
> cd iPromise
> npm install
> npm run build

###2. Include iPromise on your site. Compiled and production-ready code can be found in the dist directory.Then src directory contains development code. Unit tests are located in the test directory.

<script src="dist/iPromise.min.js"></script>
<script src="myapp.js"></script>

###3. Comparision with ordinary callback processes Now we want to do some amazing animation effection by ordinary callback process.

var el = document.getElementById('box')
var xy = {x: el.offsetLeft, y: el.offsetTop}
setTimeout(function(){
 xy.x = xy.x + 100 
 el.style.left = xy.x + 'px'
 setTimeout(function(){
 xy.x = xy.x + 100 
 el.style.left = xy.x + 'px'
 setTimeout(function(){
 xy.x = xy.x + 200 
 el.style.left = xy.x + 'px'
 }, 500)
 }, 500)
}, 500)

iPromise save our time.

var el = document.getElementById('box')
var xy = {x: el.offsetLeft, y: el.offsetTop}
iPromise
 .wait(500)
 .then(function(){
 xy.x = xy.x + 100 
 el.style.left = xy.x + 'px'
 })
 .wait(500)
 .then(function(){
 xy.x = xy.x + 100 
 el.style.left = xy.x + 'px'
 })
 .wait(500)
 .then(function(){
 xy.x = xy.x + 200 
 el.style.left = xy.x + 'px'
 })

API

###Constructor ####iPromise(mixin, arg) @description Create new iPromise object.
@param {(Function.<Function fulfilledFn,Function rejectedFn>|GeneratorFunction)} mixin - Factory function to change the status of iPromise object. Or a Generator Function(feature by ES6).
@param {...*} arg - It would be work when mixin is an instanceof GeneratorFunction.
@return {?iPromise} - The returns would be undefined when mixin is an instanceof GeneratorFunction.

/* mixin is function */
var p2 = iPromise(function(resolve, reject){
 setTimeout(function(){
 resolve('hello', 'world', '!')
 }, 5000)
})
/* returns coroutine when mixin is generator function */
var coroutine = iPromise(function* (name, city){
 console.log('Welcome to ' + city)
 var msg
 try{
 msg = yield wrapMsg(name)
 }
 catch(e){
 msg = 'Hi, ' + name
 }
 console.log(msg)
})
coroutine('fsjohnhuang', 'fs')

###Instance Methods ####iPromise#then(fulfilledFn, rejectedFn, finallyFn) @description Subscribes the iPromise object's status changed event.
@param {Function.<*>} fulfilledFn - It would be called when iPromise object's status is from pending to fulfilled
@param {Function.<*>} rejectedFn - It would be called when iPromise object's status is from pending to rejected
@param {Function.<*>} finallyFn - It would be called when iPromise object's status is changed and has subscribed fulfilled or rejected status changing event
@return {iPromise} - The subset of iPromise object which contains iPromise#then, iPromise#catch and iPromise#wait only.

iPromise(function(resolve, reject){
 resolve()
 })
 .then(function(){
 console.log('from pending to fulfilled')
 }, function(){
 console.log('from pending to rejected')
 }, function(){
 console.log('finally')
 })

####iPromise#catch(rejectedFn, finallyFn) @description Subscribes the iPromise object's status changed event which is from pending to rejected.
@param {Function.<*>} rejectedFn - It would be called when iPromise object's status is from pending to rejected
@param {Function.<*>} finallyFn - It would be called when iPromise object's status is changed and has subscribed rejected status changing event
@return {iPromise} - The subset of iPromise object which contains iPromise#then, iPromise#catch and iPromise#wait only.

iPromise(function(resolve, reject){
 reject() 
 })
 .catch(function(){
 console.log('from pending to rejected')
 }, function(){
 console.log('finally')
 })

####iPromise#wait(ms) @description Invokes the next callback function after ms milliseconds without changing the status of iPromise object.
@param {number} ms - The time to wait.
@return {iPromise} - The subset of iPromise object which contains iPromise#then, iPromise#catch and iPromise#wait only.

iPromise(function(resolve, reject){
 resolve()
 })
 .then(function(arg){
 return +new Date()
 })
 .wait(1000)
 .then(function(arg){
 console.log((+new Date()) - arg > 1000) // true
 })

###Function Properties ####iPromise.resolve(val) @description Change the status of iPromise object from pending to fulfilled.
@param {*} val - It would be as the argument of fulfilled callback function which is invoked first.

/* arg is such as ({*} arg) */
iPromise
 .resolve(1)
 .then(function(arg){
 console.log(arg)
 })
/* arg is such as ({Thenable} arg) */
iPromise
 .resolve({then:function(resolve){resolve('test')}})
 .then(function(arg){
 console.log(arg)
 })

####iPromise.reject(reason) @description Change the status of iPromise object from pending to rejected.
@param {*} arg - It would be as the argument of rejected callback function which is invoked first.

/* arg is such as ({*} arg) */
iPromise
 .reject(1)
 .then(null, function(arg){
 console.log(arg)
 })
/* arg is such as ({Thenable} arg) */
iPromise
 .reject({then:function(resolve){resolve('test')}})
 .then(function(arg){
 console.log(arg)
 })

####iPromise.all(condition) @description Change the status of iPromise object from pending to fulfilled when meets all conditions, otherwise would change status from pending to rejected
@param {...*} condition
@return {iPromise} - The subset of iPromise object which contains iPromise#then, iPromise#catch and iPromise#wait only.

a = 1
b = iPromise(function(r){
 setTimeout(function(){r(2)}, 200)
})
c = {
 then: function(r){
 setTimeout(function(){r(3)}, 600)
 }
}
var curr, o = +new Date() 
iPromise.all(a,b,c).then(function(val){
 curr = +new Date()
 console.log(curr - o > 600) // true
}

####iPromise.any(condition) / iPromise.race(condition) @description Change the status of iPromise object from pending to fulfilled when meets any condition, otherwise would change status from pending to rejected
@param {...*} condition
@return {iPromise} - The subset of iPromise object which contains iPromise#then, iPromise#catch and iPromise#wait only.

a = iPromise(function(r){
 setTimeout(function(){r(2)}, 200)
})
c = {
 then: function(r){
 setTimeout(function(){r(3)}, 600)
 }
}
var curr, o = +new Date() 
iPromise.all(b,c).then(function(val){
 curr = +new Date()
 console.log(curr - o < 300) // true
}

####iPromise.wait(ms, arg) @description Changes the status of iPromise object from pending to fulfilled after ms milliseconds.
@param {number} ms - The time to wait.
@param {...*} arg - Is would be arguments of the next fulfilled callback function.
@return {iPromise} - The subset of iPromise object which contains iPromise#then, iPromise#catch and iPromise#wait only.

iPromise
 .wait(1000, +new Date())
 .then(function(arg){
 console.log((+new Date()) - arg > 1000) // true
 })

##Changelog ###v0.8.3 bug修复

  1. 修复iPromise(function*(a){},1),a为undefined的问题。 API修改
  2. iPromise(function*(a){},1)改为
var coroutine = iPromsie(function*(a, b){})
coroutine(1, 2)

###v0.8.2 bug修复

  1. 修复后iPromise.resolve({Thenable})iPromise.reject({Thenable})方法均可将一个thenable对象转换为iPromise对象

###v0.8.1 bug修复

  1. 修复重复调用resolve或reject方法时,会覆盖之前的val和reason值的问题。现在无论调用多少次resovle或reject方法,均只有第一次调用是有效的。

###v0.8.0 全局重构

  1. 改用事件机制订阅iPromise状态变化事件从而触发相应的处理函数。
    事件机制由*TinyES(迷你事件系统模块)AsyncES(事件异步响应系统模块)*两个模块提供
  2. 删除实例方法resolve和reject。
  3. 新增类方法resolve和reject。

###v0.7.0 全局重构
新增

  1. utils模块,将原来位于iPromise模块中的辅助函数迁移到utils模块中。
    修改
  2. then({Function} fulfilledFn,{Function} rejectedFn,{Function} progressFn,{Function} finallyFn)-->then({Function} fulfilledFn,{Function} rejectedFn,{Function} finallyFn)
  3. catch({Function} rejectedFn)-->catch({Function} rejectedFn,{Function} finallyFn)
  4. iPromise.wait({Number} ms)-->iPromise.wait({Number} ms/*, ...args*/)
    删除
  5. notify()
  6. finally()

###v0.6.1 添加mocha、chai作为单元测试套件
添加blanket作为覆盖率测试库
添加npm作为依赖管理工具

###v0.6.0 bug修复

  1. #20141217 iPromise({Function} mixin),没有捕获mixin内部抛出同步异常->捕获mixin内部抛出同步异常,并将异常信息作为入参调用deferred实例的reject函数。
  2. iPromise({Function|Object} mixin?),若mixin为Object,则返回的为deferred实例,若mixin为Function,则返回的是Promise实例。
    新特性
  3. iPromise构造器接受ES6的Generator Function。并返回undefined
var getData = function(dataSrc){
 return iPromise(function(r){
 	setTimeout(function(){
 		r(dataSrc + ' has loaded')
 	}, 1000)
 })
}
var getTpl = function(tplSrc){
 return iPromise(function(r){
 	setTimeout(function(){
 		r(tplStr + ' has loaded')
 	}, 2000)
 })
}
var render = function(data, tpl){
	throw new Error('OMG!')
}
iPromise(function *(dataSrc, tplSrc){
 try{
 	var data = yield getData(dataSrc)
 	var tpl = yield getTpl(tplSrc)
 	render(data, tpl)
 }
 catch(e){
 	console.log(e)
 }
 console.log('over!')
}, 'dummyData.json', 'dummyTpl.json')
/* 结果如下 */
// 等待1秒多显示 dummyData.json has loaded
// 等待2秒多显示 dummyTpl.json has loaded
// 显示 Error: OMG!
// Stack trace:
// test10/render/</<@file:///home/fsjohnhuang/repos/iPromise/test/v0.0.2.html:190:6
// 显示 over!

###v0.5.0 新特性

  1. 新增{Promise} wait({number} ms){Promise} iPromise.wait({number} ms),等待ms毫秒在执行后续的回调函数,此方法不会改变Deferred实例状态和责任链传递的值。

##v0.4.0 bug修复

  1. #20141215 可重复添加回调函数->仅能添加一次回调函数
    新特性
  2. 新增APIiPromise.all([Object|Array}|...[*]), 当所有入参均成功返回值时则执行成功回调函数
var thenable = {
 then: function(r){
 	setTimeout(function(){
 		r('hi', 'there')
 	}, 1000)
 }
}
var name = 'fsjohnhuang'
var promise1 = iPromise(function(r){
 	setTimeout(function(){
 		r('I\'m')
 	}, 2000)
})
iPromise.all(thenable, name, promise1).then(function(arg){
	alert(arg[0][0] + ' ' + arg[0][1] + ',' + arg[2] + ' ' + arg[1]) // 两秒多后显示hi there,I'm fsjohnhuang
})
iPromise.all([thenable, name, promise1]).then(function(arg){
	alert(arg[0][0] + ' ' + arg[0][1] + ',' + arg[2] + ' ' + arg[1]) // 两秒多后显示hi there,I'm fsjohnhuang
})
iPromise.all({a:thenable, b:name, c:promise1}).then(function(arg){
	alert(arg.a[0] + ' ' + arg.a[1] + ',' + arg.c + ' ' + arg.b) // 两秒多后显示hi there,I'm fsjohnhuang
})
  1. 新增APIiPromise.any([Object|Array}|...[*]),当有一个入参成功返回时则执行成功回调函数
var thenable = {
 then: function(r){
 	setTimeout(function(){
 		r('hi', 'there')
 	}, 1000)
 }
}
var name = 'fsjohnhuang'
var promise1 = iPromise(function(r){
 	setTimeout(function(){
 		r('I\'m')
 	}, 2000)
})
iPromise.all(thenable, name, promise1).then(function(arg){
	alert(arg) // 显示fsjohnhuang
})
iPromise.all([thenable, name, promise1]).then(function(arg){
	alert(arg) // 显示fsjohnhuang
})
iPromise.all({a:thenable, b:name, c:promise1}).then(function(arg){
	alert(arg) // 显示fsjohnhuang
})

###v0.3.0 新特性

  1. 支持上一个resolveFn或rejectFn函数返回值为Promise对象时,晚绑定的resolveFn或rejectFn均可以该Promise对象作为入参被执行。
var deferred = iPromise(function(resolve){
	resolve()
})
var promise = deferred.then(function(){
	return new iPromise(function(resolve){
		resolve('hello', 'world')
	})	
})
// 一秒多后显示hello world
setTimeout(function(){
	promise.then(function(arg1, arg2){
		alert(arg1 + ' ' + arg2)	
	})	
}, 1000)
  1. 支持上一个resolveFn或rejectFn函数返回值为thenable对象时,晚绑定的resolveFn或rejectFn均可以该Promise对象作为入参被执行。
var deferred = iPromise(function(resolve){
	resolve()
})
var promise = deferred.then(function(){
	var thenable = {
		then: function(resolve){
			resolve('hello', 'world')
		}
	}	
	return thenable
})
// 一秒多后显示hello world
setTimeout(function(){
	promise.then(function(arg1, arg2){
		alert(arg1 + ' ' + arg2)	
	})	
}, 1000)

###v0.2.0 全局重构,API说明

  1. {Deferred} [new] iPromise({Object|Function<this:null,{Function} resovle, {Function} reject, {Function} notify>}),构造Deferred实例,入参为Object类型时则将入参的属性和方法附加到返回的Deferred实例上,若入参为函数则可在函数体内调用resolve、reject或notify方法触发调用Deferred实例的回调函数的请求。
  2. {Promise} then({Function} resolveFn?, {Function} rejectFn?, {Function} progressFn?, {Function} finally?),向Deferred实例添加四类回调函数。
  3. {Promise} catch({Function} rejectFn?),向Deferred实例添加rejected状态的回调函数,仅能执行一次。
  4. {Promise} progress({Function} progressFn?),向Deferred实例添加可以多次执行的回调函数
  5. {Promise} finally{Function} finallyFn?),向Deferred实例添加模拟finally语句的回调函数,在调用resovle和reject函数时必定会执行该函数,并且当该函数抛异常时会将当前Deferred的状态设置为rejected
  6. resolve(...[*])
  7. reject(...[*])
  8. notify(...[*])

特性

  1. iPromise包含Deferred和Promise两类操作集合,其中Promise是Deferred的子集,仅提供添加回调函数的功能。而Deferred集合还提供发起执行回调函数请求的功能。
  2. 回调函数支持任意数目的入参。
  3. resolveFn和rejectFn函数支持晚绑定。
var deferred = iPromise(function(resolve){
	resolve('hello', 'world')
})
setTimeout(function(){
	deferred.then(function(arg1, arg2){
		alert(arg1 + ' ' + arg2) // 一秒多后,显示hello world
	})
}, 1000)

###v0.1.0 实现基础接口API

  1. new iPromise([fn(resolve, reject)]),构造promise实例,可传入一个带resolve函数、reject函数的入参方法。
  2. then([{Function} fulfilledHandler[, {Function} rejectedHandler]]),重写fulfilled和rejected回调。
  3. resolve([{Any} data]),promise实例方法,用于触发fulfilled回调。
  4. reject([{Any} data]),promise实例方法,用于触发rejected回调。

##Referrence prmises/A+
prmises/A
JavaScript异步编程的模式
深入理解Promise五部曲

About

An implementation for promises/A+

Resources

License

Stars

Watchers

Forks

Packages

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /