Skip to content

Instantly share code, notes, and snippets.

@DC3
Last active August 29, 2015 14:11
Show Gist options
  • Save DC3/67544c90035f466866a1 to your computer and use it in GitHub Desktop.
Save DC3/67544c90035f466866a1 to your computer and use it in GitHub Desktop.
promise 示例
# 兼容 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
// 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