Last active
August 29, 2015 14:11
-
-
Save DC3/67544c90035f466866a1 to your computer and use it in GitHub Desktop.
promise 示例
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 兼容 jQuery Deferred 与 ES6 Promise 的写法的 Promise Wrapper | |
# https://gist.github.com/DC3/d2c37399eae2f7f08d16 | |
do -> | |
hasPromise = (window.Promise and window.Promise.all) | |
hasjQuery = (($ = window.jQuery) and window.jQuery.fn.jquery) | |
return if hasPromise or not hasjQuery | |
Promise = (func) -> | |
$.Deferred(({resolve, reject}) -> | |
func.call null, resolve, reject | |
).promise() | |
Promise.all = (arr) -> new Promise (resolve, reject) -> | |
if Object::toString.call(arr) isnt '[object Array]' | |
throw new TypeError 'Promise.all first param must be An iterable object' | |
handleArguments = (args...) -> resolve(args) | |
$.when(arr...).then(handleArguments , reject) | |
Promise.resolve = -> $.Deferred().resolve arguments... | |
Promise.reject = -> $.Deferred().reject arguments... | |
# Promise.race = -> # WARN: jQuery do not have race method | |
window.Promise = Promise | |
# 简洁写法 单行构建 | |
# 第一个箭头前可接受各种传参,第二个为 Promise 固定的参数 | |
# 常用 Promise 实例 | |
delay = (time) -> new Promise (resolve) -> setTimeout resolve, time | |
waitFor = (el, ev, useCapture = false) -> new Promise (resolve, reject) -> | |
el.addEventListener(ev, fn = (e) -> | |
resolve(e) | |
@removeEventListener ev, fn, useCapture | |
, useCapture) | |
loadImg = (url) -> new Promise (resolve, reject) -> | |
img = new Image | |
img.addEventListener 'error', reject | |
img.addEventListener 'load', fn = (e) -> | |
resolve(e) | |
@removeEventListener 'load', fn | |
img.src = url | |
DOMReady = -> new Promise (resolve, reject) -> | |
if document.readyState is 'complete' | |
resolve() | |
else | |
document.addEventListener 'DOMContentLoaded', resolve | |
# test case helpers | |
range = (length) -> Array.apply(null, {length}).map(Number.call, Number) | |
makeSyncPromise = (val) -> Promise.resolve(val) | |
makeAsyncPromise = (val, time) -> | |
delay(time).then -> | |
console.info("makeAsyncPromise val: #{val} delay: #{time}") | |
val | |
makeAsyncItemPromise = (val, index) -> | |
delay((time = index * 100)).then -> | |
console.debug("makeAsyncItemPromise val: #{val} index: #{index} delay: #{time}") | |
val | |
#makeAsyncPromise = (val, index) -> new Promise (resolve) -> | |
#setTimeout resolve.bind(null, val), index * 100 | |
# 同步 promise | |
syncPromiseA = -> | |
console.info('syncPromiseA done, no delay.') | |
makeSyncPromise(123) | |
syncPromiseB = -> | |
console.info('syncPromiseB done, no delay.') | |
makeSyncPromise(456) | |
# 异步 promise | |
asyncPromiseA = (val = 111) -> makeAsyncPromise(val, 500).then -> val | |
asyncPromiseB = (val = 222)-> makeAsyncPromise(val, 400).then -> val | |
# ======= 测试例子 ======== | |
# | |
DOMReady() | |
.then syncPromiseA | |
.then asyncPromiseA | |
.then asyncPromiseB | |
#.then Promise.reject # 取消注释看跳出 | |
.then syncPromiseB | |
.then (result) -> | |
console.info '按顺序执行,任意一个流程都可以中断退出流程,只能拿最后一个结果', result | |
Promise.all([ | |
syncPromiseB(), asyncPromiseB(), | |
asyncPromiseA(), syncPromiseA() | |
]).then (results) -> | |
console.info '等待全部完成的之后拿所有结果', results | |
# 函数式编程方式处理批量并发 promises | |
Promise.all(range(10).map(Math.random).map(makeAsyncItemPromise)) | |
.then (results) -> | |
console.info '所有的都完成才会到我', results | |
# 递归 | |
range(10).map(Math.random).reduce((seq, val, index) -> | |
seq.then -> makeAsyncItemPromise(val, index) | |
, Promise.resolve()) | |
.then (result) -> | |
console.info '我会按顺序执行,并返回最后一个结果', result | |
Promise.race?(range(10).map(Math.random).map(makeAsyncItemPromise)) | |
.then (result) -> | |
console.info '任意一个最快的完成就够了,其他的返回我不管', result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Generated by CoffeeScript 1.9.0 | |
var DOMReady, asyncPromiseA, asyncPromiseB, delay, loadImg, makeAsyncItemPromise, makeAsyncPromise, makeSyncPromise, range, syncPromiseA, syncPromiseB, waitFor, | |
__slice = [].slice; | |
(function() { | |
var $, Promise, hasPromise, hasjQuery; | |
hasPromise = window.Promise && window.Promise.all; | |
hasjQuery = ($ = window.jQuery) && window.jQuery.fn.jquery; | |
if (hasPromise || !hasjQuery) { | |
return; | |
} | |
Promise = function(func) { | |
return $.Deferred(function(_arg) { | |
var reject, resolve; | |
resolve = _arg.resolve, reject = _arg.reject; | |
return func.call(null, resolve, reject); | |
}).promise(); | |
}; | |
Promise.all = function(arr) { | |
return new Promise(function(resolve, reject) { | |
var handleArguments; | |
if (Object.prototype.toString.call(arr) !== '[object Array]') { | |
throw new TypeError('Promise.all first param must be An iterable object'); | |
} | |
handleArguments = function() { | |
var args; | |
args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; | |
return resolve(args); | |
}; | |
return $.when.apply($, arr).then(handleArguments, reject); | |
}); | |
}; | |
Promise.resolve = function() { | |
var _ref; | |
return (_ref = $.Deferred()).resolve.apply(_ref, arguments); | |
}; | |
Promise.reject = function() { | |
var _ref; | |
return (_ref = $.Deferred()).reject.apply(_ref, arguments); | |
}; | |
return window.Promise = Promise; | |
})(); | |
delay = function(time) { | |
return new Promise(function(resolve) { | |
return setTimeout(resolve, time); | |
}); | |
}; | |
waitFor = function(el, ev, useCapture) { | |
if (useCapture == null) { | |
useCapture = false; | |
} | |
return new Promise(function(resolve, reject) { | |
var fn; | |
return el.addEventListener(ev, fn = function(e) { | |
resolve(e); | |
return this.removeEventListener(ev, fn, useCapture); | |
}, useCapture); | |
}); | |
}; | |
loadImg = function(url) { | |
return new Promise(function(resolve, reject) { | |
var fn, img; | |
img = new Image; | |
img.addEventListener('error', reject); | |
img.addEventListener('load', fn = function(e) { | |
resolve(e); | |
return this.removeEventListener('load', fn); | |
}); | |
return img.src = url; | |
}); | |
}; | |
DOMReady = function() { | |
return new Promise(function(resolve, reject) { | |
if (document.readyState === 'complete') { | |
return resolve(); | |
} else { | |
return document.addEventListener('DOMContentLoaded', resolve); | |
} | |
}); | |
}; | |
range = function(length) { | |
return Array.apply(null, { | |
length: length | |
}).map(Number.call, Number); | |
}; | |
makeSyncPromise = function(val) { | |
return Promise.resolve(val); | |
}; | |
makeAsyncPromise = function(val, time) { | |
return delay(time).then(function() { | |
console.info("makeAsyncPromise val: " + val + " delay: " + time); | |
return val; | |
}); | |
}; | |
makeAsyncItemPromise = function(val, index) { | |
var time; | |
return delay((time = index * 100)).then(function() { | |
console.debug("makeAsyncItemPromise val: " + val + " index: " + index + " delay: " + time); | |
return val; | |
}); | |
}; | |
syncPromiseA = function() { | |
console.info('syncPromiseA done, no delay.'); | |
return makeSyncPromise(123); | |
}; | |
syncPromiseB = function() { | |
console.info('syncPromiseB done, no delay.'); | |
return makeSyncPromise(456); | |
}; | |
asyncPromiseA = function(val) { | |
if (val == null) { | |
val = 111; | |
} | |
return makeAsyncPromise(val, 500).then(function() { | |
return val; | |
}); | |
}; | |
asyncPromiseB = function(val) { | |
if (val == null) { | |
val = 222; | |
} | |
return makeAsyncPromise(val, 400).then(function() { | |
return val; | |
}); | |
}; | |
DOMReady().then(syncPromiseA).then(asyncPromiseA).then(asyncPromiseB).then(Promise.reject).then(syncPromiseB).then(function(result) { | |
return console.info('按顺序执行,任意一个流程都可以中断退出流程,只能拿最后一个结果', result); | |
}); | |
Promise.all([syncPromiseB(), asyncPromiseB(), asyncPromiseA(), syncPromiseA()]).then(function(results) { | |
return console.info('等待全部完成的之后拿所有结果', results); | |
}); | |
Promise.all(range(10).map(Math.random).map(makeAsyncItemPromise)).then(function(results) { | |
return console.info('所有的都完成才会到我', results); | |
}); | |
range(10).map(Math.random).reduce(function(seq, val, index) { | |
return seq.then(function() { | |
return makeAsyncItemPromise(val, index); | |
}); | |
}, Promise.resolve()).then(function(result) { | |
return console.info('我会按顺序执行,并返回最后一个结果', result); | |
}); | |
if (typeof Promise.race === "function") { | |
Promise.race(range(10).map(Math.random).map(makeAsyncItemPromise)).then(function(result) { | |
return console.info('任意一个最快的完成就够了,其他的返回我不管', result); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment