Skip to content

Instantly share code, notes, and snippets.

@weirongxu
Last active August 29, 2015 14:07
Show Gist options
  • Save weirongxu/0e9101e77611a2b234d3 to your computer and use it in GitHub Desktop.
Save weirongxu/0e9101e77611a2b234d3 to your computer and use it in GitHub Desktop.
angular $q queue
require 'app'
.factory 'Promise', [
'$q'
(
$q
)->
# $q 和 Promise 都兼容的方法
# @example 1)
# new Promise (resolve, reject, notify)->
# if flag
# resolve true
# else
# reject false
# @example 2) FIXME
# new Promise ->
# if flag
# @resolve true
# else
# @reject false
#
# @example 3)
# Promise (resolve, reject, notify)->
# if flag
# resolve true
# else
# reject false
#
# @example 4) FIXME
# Promise ->
# if flag
# @resolve true
# else
# @reject false
# @example 5)
# deferral = Promise.defer()
# if flag
# deferral.resolve true
# else
# deferral.reject true
# deferral.promise
p = (fn) ->
deferred = $q.defer()
fn.notify = (args...)->
deferred.notify args...
fn.resolve = (args...)->
deferred.resolve args...
fn.reject = (args...)->
deferred.reject args...
fn fn.resolve, fn.reject, fn.notify
@then = (args...)->
deferred.promise.then args...
@catch = (args...)->
deferred.promise.catch args...
@finally = (args...)->
deferred.promise.finally args...
deferred.promise
p.defer = ()->
$q.defer()
p.resolve = (args...)->
$q.when args...
p.when = (args...)->
$q.when args...
p.reject = (reason)->
deferred = $q.defer()
deferred.reject reason
deferred.promise
p.all = (promises)->
$q.all promises
# TODO
# p.allSettled = (promises)->
# # 同kriskowal/q的allSettled
# # Q.allSettled(promises).then (results) ->
# # results.forEach (result) ->
# # if result.state is 'fulfilled'
# # value = result.value
# # else
# # reason = result.reason
p.anyall = (promises)->
# 与$q.all不同的方法
# 在碰到reject时, 赋值为null, 并不中止.
deferred = $q.defer()
counter = 0
results = (if angular.isArray(promises) then [] else {})
resolve = (key, value)->
if results.hasOwnProperty(key)
return
results[key] = value
unless --counter
deferred.resolve results
angular.forEach promises, (promise, key) ->
counter++
$q.when(promise).then (value) ->
resolve key, value
, (reason) ->
resolve key, null
if counter is 0
deferred.resolve results
deferred.promise
# TODO
# p.race = (promises)->
# p.spread
# 队列方式去执行promise,
# 让promise执行方式为非异步,
# 防止获取重复的数据
#
# @example 简单示例
# Promise.queue promies, (promise)->
# return Promise.resolve promise
# , (data, key, promises)->
# console.log 'success'
# true
# , (reason, key, promises)->
# console.log 'error'
# true
# .then (datas)->
# console.log 'success'
# .catch (reasons)->
# console.log 'success'
#
# @example 队列方式去获取用户信息
# _user = {} # 用户缓存数组, 这样就不会重复获取Levi
# Promise.queue ['Jang', 'Levi', 'Kirito', 'Asuna', 'Levi', 'Levi'], (username)->
# if username of _user
# return Promise.resolve _user[username]
# # 等于 return $q.when _user[username]
# else
# return $http.get '/username/#{username}'
# , (user, key, usernames)->
# console.log "#{usernames[key]}'s info as follow"
# console.dir user
# true
# , (reason)->
# console.log 'error'
# true
# .then (users)->
# console.table users
# .catch (reasons)->
# console.log reason
#
# @param promise_array [Array]
# 数组 (可以是一般数据 或 primise)
#
# @param getPromise [Function] 同步队列本体
# Function(promise)
# @param promise [mixin] 来自promise_array
# @return [Promise] 返回用于同步执行的Promise, 返回false表示忽略这个promise.
#
# @param success [Function]
# Function(data, key, promise_array)
# @param data 每次获取到的数据
# @param key 每次获取到的元值索引
# @param promise_array 源数组
# @return [Boolean] 返回false终止运行, 并调用reject
#
# @param error [Function]
# Function(data, key, source_promise)
# @param data reject后获取到的reason
# @param key 每次获取到的元值索引
# @param promise_array 源数组
# @return [Boolean] 返回false终止运行, 并调用reject
p.queue = (promise_array, getPromise, success=null, error=null)->
deferred = $q.defer()
p.anyall promise_array
.then (items)->
resolves = []
reasons = []
stack = []
for value, key in items
stack.push
key: key
value: value
do recursion = ->
if item = stack.shift()
if (promise = getPromise item.value) isnt false
promise.then (value)->
resolves.push value
if not success || success(value, item.key, items)
recursion()
else
deferred.reject reasons
, (reason)->
reasons.push reason
if not error || error(reason, item.key, items)
recursion()
else
deferred.reject reasons
else
recursion()
else
if reasons.length
deferred.reject reasons
else
deferred.resolve resolves
deferred.promise
p
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment