promise-queue-plus.js 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. /*!
  2. * promise-queue-plus v1.1.0
  3. * Homepage https://github.com/cnwhy/promise-queue-plus
  4. * License BSD-2-Clause
  5. */
  6. (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  7. (function (name, factory) {
  8. if (typeof define === 'function' && (define.amd || define.cmd)) {
  9. define([], factory);
  10. } else if (typeof window !== "undefined" || typeof self !== "undefined") {
  11. var global = typeof window !== "undefined" ? window : self;
  12. global[name] = factory();
  13. } else {
  14. throw new Error('Loading the "' + name + '" module failed!');
  15. }
  16. }('PromiseQueuePlus', function () {
  17. return require('../src/queue')(require('easy-promise/setTimeout'));
  18. }));
  19. },{"../src/queue":6,"easy-promise/setTimeout":2}],2:[function(require,module,exports){
  20. module.exports = require("./src")(function(fn){setTimeout(fn,0)});
  21. },{"./src":3}],3:[function(require,module,exports){
  22. "use strict";
  23. module.exports = function(nextTick){
  24. var FUN = function(){};
  25. function Resolve(promise, x) {
  26. if(isPromise(x)){
  27. x.then(promise.resolve,promise.reject)
  28. }else if (x && (typeof x === 'function' || typeof x === 'object')) {
  29. var called = false,then;
  30. try {
  31. then = x.then;
  32. if (typeof then === 'function') {
  33. then.call(x, function(y) {
  34. if (called) return;
  35. called = true;
  36. Resolve(promise, y);
  37. }, function(r) {
  38. if (called) return;
  39. called = true;
  40. promise.reject(r);
  41. });
  42. }else {
  43. promise.resolve(x);
  44. }
  45. }catch (e) {
  46. if (!called) {
  47. called = true;
  48. promise.reject(e);
  49. }
  50. }
  51. }else {
  52. promise.resolve(x);
  53. }
  54. }
  55. function isPromise(obj){
  56. return obj instanceof Promise_;
  57. }
  58. function bind(fun,self){
  59. var arg = Array.prototype.slice.call(arguments,2);
  60. return function(){
  61. fun.apply(self,arg.concat(Array.prototype.slice.call(arguments)));
  62. }
  63. }
  64. function Promise_(fun){
  65. //var defer = this.defer = new Defer(this);
  66. var self = this;
  67. this.status = -1; //pending:-1 ; fulfilled:1 ; rejected:0
  68. this._events = [];
  69. var lock = false;
  70. function _resolve(value){
  71. changeStatus.call(self,1,value)
  72. }
  73. function _reject(reason){
  74. changeStatus.call(self,0,reason)
  75. }
  76. function resolve(value){
  77. if(lock) return;
  78. lock = true;
  79. if(self === value){
  80. return _reject(new TypeError("The promise and its value refer to the same object"));
  81. }
  82. Resolve({resolve:_resolve,reject:_reject},value)
  83. }
  84. function reject(reason){
  85. if(lock) return;
  86. lock = true;
  87. _reject(reason);
  88. }
  89. this.resolve = resolve;
  90. this.reject = reject;
  91. if(fun !== FUN && typeof fun == "function"){
  92. try{
  93. fun(this.resolve,this.reject);
  94. }catch(e){
  95. this.reject(e)
  96. }
  97. }
  98. }
  99. Promise_.defer = function(){
  100. var _promise = new Promise_(FUN);
  101. return {
  102. promise: _promise,
  103. resolve: _promise.resolve,
  104. reject: _promise.reject
  105. }
  106. }
  107. Promise_.resolve = function(obj){
  108. if(isPromise(obj)) return obj;
  109. return new Promise_(function(ok,no){
  110. ok(obj);
  111. })
  112. }
  113. Promise_.reject = function(err){
  114. return new Promise_(function(ok,no){
  115. no(err);
  116. })
  117. }
  118. Promise_.prototype.toString = function () {
  119. return "[object Promise]";
  120. }
  121. Promise_.prototype.then = function(ok,no){
  122. var status = this.status;
  123. var defer = Promise_.defer()
  124. ,promise = defer.promise
  125. if(!~status){
  126. this._events.push([ok,no,promise]);
  127. }else if(status && typeof ok == "function"){
  128. runThen(ok,this.value,promise,status);
  129. }else if(!status && typeof no == "function"){
  130. runThen(no,this.reason,promise,status)
  131. }else{
  132. if(status) defer.resolve(this.value)
  133. else defer.reject(this.reason);
  134. }
  135. // this._events.push([ok,no,promise]);
  136. // runThens.call(this)
  137. return promise;
  138. }
  139. function changeStatus(status,arg){
  140. var self = this;
  141. if(~this.status) return;
  142. this.status = status;
  143. if(status){
  144. this.value = arg
  145. }else{
  146. this.reason = arg;
  147. }
  148. runThens.call(self)
  149. }
  150. function runThens(){
  151. if(!~this.status) return;
  152. var self = this
  153. ,_event = self._events
  154. ,arg = self.status ? self.value : self.reason
  155. ,FnNumb = self.status ? 0 : 1;
  156. //while(_event.length){
  157. for(var i=0; i<_event.length; i++){
  158. (function(eArr){
  159. var resolve,reject
  160. var fn = eArr[FnNumb]
  161. ,nextQ = eArr[2]
  162. runThen(fn,arg,nextQ,self.status);
  163. })(_event[i])
  164. // })(_event.shift())
  165. }
  166. _event = [];
  167. }
  168. function runThen(fn,arg,nextQ,status){
  169. var resolve = nextQ.resolve
  170. ,reject = nextQ.reject
  171. // if(nextQ){
  172. // resolve = nextQ.resolve
  173. // reject = nextQ.reject
  174. // }
  175. if(typeof fn == 'function'){
  176. nextTick(function(){
  177. var nextPromise;
  178. try{
  179. nextPromise = fn(arg)
  180. }catch(e){
  181. reject(e)
  182. // if(reject)
  183. // else throw e;
  184. return;
  185. }
  186. resolve(nextPromise);
  187. })
  188. }else{
  189. if (status) resolve(arg)
  190. else reject(arg)
  191. }
  192. }
  193. return Promise_;
  194. }
  195. },{}],4:[function(require,module,exports){
  196. 'use strict';
  197. var utils = require('./utils')
  198. var isArray = utils.isArray
  199. ,isEmpty = utils.isEmpty
  200. ,isFunction = utils.isFunction
  201. ,isPlainObject = utils.isPlainObject
  202. ,arg2arr = utils.arg2arr
  203. function extendClass(Promise,obj,funnames){
  204. var QClass,source;
  205. if(obj){
  206. source = true
  207. QClass = obj;
  208. }else{
  209. QClass = Promise;
  210. }
  211. function asbind(name){
  212. if(isArray(funnames)){
  213. var nomark = false;
  214. for(var i = 0; i<funnames.length; i++){
  215. if(funnames[i] == name){
  216. nomark = true;
  217. break;
  218. }
  219. }
  220. if(!nomark) return false;
  221. }
  222. if(source){
  223. return !isFunction(QClass[name]);
  224. }
  225. return true;
  226. }
  227. if(!QClass.Promise && Promise != obj) QClass.Promise = Promise;
  228. //defer defer为最基础的实现
  229. if(isFunction(Promise) && isFunction(Promise.prototype.then)){
  230. QClass.defer = function() {
  231. var resolve, reject;
  232. var promise = new Promise(function(_resolve, _reject) {
  233. resolve = _resolve;
  234. reject = _reject;
  235. });
  236. return {
  237. promise: promise,
  238. resolve: resolve,
  239. reject: reject
  240. };
  241. }
  242. }else if(isFunction(Promise.defer)){
  243. QClass.defer = function(){return Promise.defer();}
  244. }else if(isFunction(Promise.deferred)){
  245. QClass.defer = function(){return Promise.deferred();}
  246. }else{
  247. throw new TypeError("此类不支持扩展!")
  248. }
  249. //delay
  250. if(asbind("delay")){
  251. QClass.delay = function(ms,value){
  252. var defer = QClass.defer();
  253. setTimeout(function(){
  254. //console.log('==========')
  255. defer.resolve(value);
  256. },ms)
  257. return defer.promise;
  258. }
  259. }
  260. //resolve
  261. if(asbind("resolve")){
  262. QClass.resolve = function(obj){
  263. var defer = QClass.defer();
  264. defer.resolve(obj);
  265. return defer.promise;
  266. }
  267. }
  268. //reject
  269. if(asbind("reject")){
  270. QClass.reject = function(obj){
  271. var defer = QClass.defer();
  272. defer.reject(obj);
  273. return defer.promise;
  274. }
  275. }
  276. function getall(map,count){
  277. if(!isEmpty(count)){
  278. count = +count > 0 ? +count : 0;
  279. }
  280. return function(promises) {
  281. var defer = QClass.defer();
  282. var data,_tempI = 0;
  283. var fillData = function(i){
  284. var _p = promises[i];
  285. QClass.resolve(_p).then(function(d) {
  286. if(typeof count != 'undefined'){
  287. data.push(d);
  288. }else{
  289. data[i] = d;
  290. }
  291. if (--_tempI == 0 || (!map && count && data.length>=count)) {
  292. defer.resolve(data);
  293. }
  294. }, function(err) {
  295. if (isEmpty(count)) {
  296. defer.reject(err);
  297. }else if(--_tempI == 0){
  298. defer.resolve(data);
  299. }
  300. })
  301. _tempI++;
  302. }
  303. if(isArray(promises)){
  304. data = [];
  305. if(promises.length == 0){defer.resolve(data)};
  306. for(var i = 0; i<promises.length; i++){
  307. fillData(i);
  308. }
  309. }else if(map && isPlainObject(promises)){
  310. var _mark = 0;
  311. data = {}
  312. for(var i in promises){
  313. fillData(i);
  314. _mark++;
  315. }
  316. if(_mark == 0) defer.resolve(data)
  317. }else{
  318. defer.reject(new TypeError("参数错误"));
  319. }
  320. return defer.promise;
  321. }
  322. }
  323. //all
  324. if(asbind("all")){
  325. QClass.all = getall()
  326. }
  327. if(asbind("allMap")){
  328. QClass.allMap = getall(true);
  329. }
  330. if(asbind("some")){
  331. QClass.some = function(proArr,count){
  332. count = +count >= 0 ? +count : 0;
  333. return getall(false,count)(proArr)
  334. }
  335. }
  336. //map
  337. if(asbind("map")){
  338. QClass.map = function(data,mapfun,options){
  339. var defer = QClass.defer();
  340. var promiseArr = [];
  341. var concurrency = options ? +options.concurrency : 0
  342. //无并发控制
  343. if(concurrency == 0 || concurrency != concurrency){
  344. for(var i in data){
  345. promiseArr.push(mapfun(data[i],i,data));
  346. }
  347. QClass.all(promiseArr).then(defer.resolve,defer.reject)
  348. return defer.promise;
  349. }
  350. var k = 0;
  351. var keys = (function(){
  352. var ks = [];
  353. for(var k in data){
  354. ks.push(k);
  355. }
  356. return ks;
  357. })();
  358. function next(){
  359. if(k<keys.length){
  360. var key = keys[k];
  361. var promise = QClass.resolve(mapfun(data[key],key,data)).then(function(v){
  362. next();
  363. return v;
  364. },defer.reject);
  365. promiseArr.push(promise);
  366. concurrency--;
  367. k++;
  368. }else{
  369. QClass.all(promiseArr).then(defer.resolve,defer.reject);
  370. }
  371. }
  372. do{
  373. next()
  374. }while(concurrency>0 && k<keys.length)
  375. return defer.promise
  376. }
  377. }
  378. function race(proArr) {
  379. var defer = QClass.defer();
  380. for (var i = 0; i < proArr.length; i++) {
  381. (function() {
  382. var _i = i;
  383. var _p = proArr[_i];
  384. QClass.resolve(_p).then(function(data) {
  385. defer.resolve(data);
  386. }, function(err) {
  387. defer.reject(err);
  388. })
  389. })()
  390. }
  391. return defer.promise;
  392. }
  393. //any | race
  394. if(asbind("race")){
  395. QClass.race = race;
  396. }
  397. if(asbind("any")){
  398. QClass.any = race;
  399. }
  400. /*封装CPS*/
  401. //callback Adapter
  402. function cbAdapter(defer){
  403. return function(err,data){
  404. if(err) return defer.reject(err);
  405. defer.resolve(data)
  406. }
  407. }
  408. function nfcall(f){
  409. var _this = this === QClass ? null : this;
  410. var defer = QClass.defer();
  411. var argsArray = arg2arr(arguments,1)
  412. argsArray.push(cbAdapter(defer))
  413. f.apply(_this,argsArray)
  414. return defer.promise;
  415. }
  416. if(asbind("nfcall")){
  417. QClass.nfcall = nfcall;
  418. }
  419. if(asbind("nfapply")){
  420. QClass.nfapply = function(f,args){
  421. var _this = this === QClass ? null : this;
  422. var defer = QClass.defer();
  423. if(isArray(args)){
  424. args.push(cbAdapter(defer));
  425. f.apply(_this,args)
  426. }else{
  427. throw TypeError('"args" is not Array')
  428. }
  429. return defer.promise;
  430. }
  431. }
  432. QClass.denodeify = function(f){
  433. var _this = this === QClass ? null : this;
  434. return function(){
  435. return nfcall.apply(_this,[].concat([f],arg2arr(arguments)))
  436. }
  437. }
  438. return QClass;
  439. }
  440. module.exports = extendClass;
  441. },{"./utils":5}],5:[function(require,module,exports){
  442. 'use strict';
  443. exports.isPlainObject = function(obj) {
  444. if (obj === null || typeof(obj) !== "object" || obj.nodeType || (obj === obj.window)) {
  445. return false;
  446. }
  447. if (obj.constructor && !Object.prototype.hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf")) {
  448. return false;
  449. }
  450. return true;
  451. }
  452. exports.isArray = function(obj){
  453. return Object.prototype.toString.call(obj) == "[object Array]"
  454. }
  455. exports.isFunction = function(obj){
  456. return typeof obj == "function"
  457. }
  458. exports.isEmpty = function(obj){
  459. return typeof obj == 'undefined' || obj === null;
  460. }
  461. exports.arg2arr = function(arg,b,s){
  462. return Array.prototype.slice.call(arg,b,s);
  463. }
  464. },{}],6:[function(require,module,exports){
  465. "use strict";
  466. var epc = require("extend-promise/src/extendClass");
  467. var utils = require("./utils");
  468. function use(Promise){
  469. var _Promise;
  470. setPromise(Promise);
  471. var ONERROR = function(err){
  472. try{
  473. console.error(err);
  474. }catch(e){}
  475. };
  476. function setPromise(Promise){
  477. _Promise = Queue.Q = Queue.Promise = epc(Promise,{});
  478. };
  479. function maxFormat(max){
  480. var _max = (+max)>>0;
  481. if(_max > 0){
  482. return _max;
  483. }else{
  484. throw new Error('The "max" value is invalid')
  485. }
  486. }
  487. function toPromise(fn){
  488. try{
  489. return _Promise.resolve(fn());
  490. }catch(e){
  491. return _Promise.reject(e);
  492. }
  493. }
  494. /**
  495. * 队列类
  496. * @param {Number} max 队列最大并行数
  497. * @param {Number} options 队列其他配置
  498. */
  499. function Queue(max,options) {
  500. var self = this;
  501. // var def = {
  502. // "event_queue_begin":null //队列开始
  503. // ,"event_queue_end":null //队列完成
  504. // ,"event_queue_add":null //有执行项添加进执行单元后执行
  505. // ,"event_item_resolve":null //成功
  506. // ,"event_item_reject":null //失败
  507. // ,"event_item_finally":null //一个执行单元结束后
  508. // ,"retry":0 //执行单元出错重试次数
  509. // ,"retry_type":0 //重试模式 0/false:搁置执行(插入队列尾部重试),1/true:优先执行 (插入队列头部重试)
  510. // ,"timeout":0 //执行单元超时时间(毫秒)
  511. // }
  512. var def = {
  513. "queueStart" : null //队列开始
  514. ,"queueEnd" : null //队列完成
  515. ,"workAdd" : null //有执行项添加进执行单元后执行
  516. ,"workResolve": null //成功
  517. ,"workReject" : null //失败
  518. ,"workFinally": null //一个执行单元结束后
  519. ,"retry" : 0 //执行单元出错重试次数
  520. ,"retryIsJump": false //重试模式 false:搁置执行(插入队列尾部重试),true:优先执行 (插入队列头部重试)
  521. ,"timeout" : 0 //执行单元超时时间(毫秒)
  522. }
  523. var _queue = [];
  524. var _max = maxFormat(max);
  525. var _runCount = 0;
  526. var _isStart = false;
  527. var _isStop = 0;
  528. this._options = def
  529. this.onError = ONERROR;
  530. if(utils.isObject(options)){
  531. for(var i in options){
  532. if(def.hasOwnProperty(i)) def[i] = options[i]
  533. }
  534. }
  535. //最大并行数
  536. this.getMax = function(){
  537. return _max;
  538. }
  539. this.setMax = function(max){
  540. try{
  541. _max = maxFormat(max);
  542. if(!_isStop && _runCount) self.start();
  543. }catch(e){
  544. onError.call(self,e)
  545. }
  546. }
  547. //正在排队的项数
  548. this.getLength = function(){
  549. return _queue.length;
  550. }
  551. //正在运行的项数
  552. this.getRunCount = function(){
  553. return _runCount;
  554. }
  555. //队列是否已开始运行
  556. this.isStart = function(){
  557. return !!_isStart;
  558. }
  559. /**
  560. * 向队列插入执行单元
  561. * @param {queueUnit} unit 执行单元对像
  562. * @param {bool} stack 是否以栈模式(后进先出)插入
  563. * @param {bool} start 是否启动队列
  564. * @param {bool} noAdd 是否调用队列workAdd方法 (重试模式不调用需要)
  565. */
  566. this._addItem = function(unit,stack,start,noAdd){
  567. if(!(unit instanceof QueueUnit)) throw new TypeError('"unit" is not QueueUnit')
  568. if(stack){
  569. _queue.unshift(unit);
  570. }else{
  571. _queue.push(unit);
  572. }
  573. noAdd || runAddEvent.call(self,unit);
  574. if(start){
  575. self.start();
  576. }else{
  577. _isStart && queueRun();
  578. }
  579. }
  580. //执行下一项
  581. function next(){
  582. if(_runCount < _max && !_isStop && _queue.length > 0){
  583. var unit = _queue.shift()
  584. //if(unit){
  585. var xc_timeout
  586. ,_mark=0
  587. var timeout = +getOption('timeout',unit,self)
  588. ,retryNo = getOption('retry',unit,self)
  589. ,retryType = getOption('retryIsJump',unit,self)
  590. ,_self = unit._options.self
  591. var fix = function(){
  592. if(xc_timeout) clearTimeout(xc_timeout)
  593. xc_timeout = 0;
  594. if(_mark++) return true;
  595. _runCount--;
  596. }
  597. var afinally = function(){
  598. autoRun(unit,self,'workFinally',self,self,unit)
  599. // if(runEvent.call(unit,'workFinally',self,self,unit) !== false){
  600. // onoff && runEvent.call(self,'workFinally',self,self,unit);
  601. // }
  602. }
  603. var issucc = function(data){
  604. if(fix()) return;
  605. unit.defer.resolve(data); //通知执行单元,成功
  606. autoRun(unit,self,'workResolve',self,data,self,unit)
  607. // if(runEvent.call(unit,'workResolve',self,data,self,unit) !== false){
  608. // onoff && runEvent.call(self,'workResolve',self,data,self,unit);
  609. // }
  610. afinally();
  611. }
  612. var iserr = function(err){
  613. if(fix()) return;
  614. if(retryNo > unit._errNo++){
  615. self._addItem(unit,retryType,true,false)
  616. }else{
  617. unit.defer.reject(err); //通知执行单元,失败
  618. autoRun(unit,self,'workReject',self,err,self,unit)
  619. // if(runEvent.call(unit,'workReject',self,err,self,unit) !== false){
  620. // onoff && runEvent.call(self,'workReject',self,err,self,unit);
  621. // }
  622. }
  623. afinally();
  624. };
  625. //队列开始执行事件
  626. if(_runCount == 0 && !_isStart){
  627. _isStart = true;
  628. runEvent.call(self,'queueStart',self,self);
  629. }
  630. var nextp = toPromise(function(){
  631. return unit.fn.apply((_self || null),unit.regs)
  632. }).then(issucc,iserr).then(function(){
  633. if(_queue.length>0){
  634. queueRun();
  635. }else if(_runCount == 0 && _isStart){//队列结束执行事件
  636. _isStart = false;
  637. runEvent.call(self,'queueEnd',self,self);
  638. }
  639. });
  640. _runCount += 1;
  641. //nextp.then(defer.resolve,defer.reject)
  642. if(timeout > 0){
  643. xc_timeout = setTimeout(function(){
  644. iserr("timeout")
  645. },timeout)
  646. }
  647. //return;
  648. //}
  649. return;
  650. }
  651. return true;
  652. }
  653. function queueRun(){
  654. while(!next()){}
  655. // if(_isStop) return;
  656. // do{
  657. // next();
  658. // }while(_queue.length && _runCount < _max)
  659. }
  660. /**队列控制**/
  661. //开始执行队列
  662. this.start = function(){
  663. _isStop = 0;
  664. queueRun();
  665. }
  666. this.stop = function(){
  667. //console.log('on stop')
  668. _isStop = 1;
  669. }
  670. //清空执行队列
  671. this.clear = function(err){
  672. while(_queue.length){
  673. var unit = _queue.shift();
  674. unit.defer.reject(err);
  675. }
  676. }
  677. }
  678. /**
  679. * 队列执行单类
  680. * @param {Function} fn 运行函数
  681. * @param {Array} args 元行函数的参数,可省略
  682. * @param {Object} options 其他配置
  683. */
  684. function QueueUnit(fn, args, options){
  685. var def = {
  686. 'workResolve' : true
  687. ,'workReject' : true
  688. ,'workFinally' : true
  689. ,'queueEventTrigger' : true
  690. ,'regs':[]
  691. ,'self':null
  692. }
  693. var oNames = [
  694. 'workResolve' //是否执行队列workResolve事件
  695. ,'workReject' //是否执行队列workReject事件
  696. ,'workFinally' //是否执行队列workFinally事件
  697. ,'queueEventTrigger' //队列事件开关
  698. ,'retry' //重试次数
  699. ,'retryIsJump' //重试模式
  700. ,'timeout' //超时
  701. ,'self' //运行函数self
  702. ];
  703. var oi = 1;
  704. if(!utils.isFunction(fn)){
  705. throw new TypeError("Queues only support function, '" + fn + "' is not function")
  706. }
  707. this.fn = fn;
  708. this._errNo = 0;
  709. this.defer = _Promise.defer();
  710. if(utils.isArray(args)){
  711. this.regs = args;
  712. oi++;
  713. }
  714. function inOptions(name){
  715. for(var i = 0; i<oNames.length; i++){
  716. if(name === oNames[i]) return true;
  717. }
  718. return false;
  719. }
  720. this._options = def;
  721. var configObj = arguments[oi];
  722. //console.log(configObj);
  723. if(utils.isObject(configObj)){
  724. for(var i in configObj){
  725. if(inOptions(i)){
  726. def[i] = configObj[i];
  727. }
  728. }
  729. }
  730. }
  731. function getOption(name,qobj,queue){
  732. if(name in qobj._options){
  733. return qobj._options[name];
  734. }else{
  735. return queue._options[name];
  736. }
  737. }
  738. function runEvent(eventName,self){
  739. var event = this._options[eventName]
  740. ,arg = utils.arg2arr(arguments,2);
  741. if(utils.isFunction(event)){
  742. try{
  743. return event.apply(self,arg)
  744. }catch(e){
  745. onError.call(self,e);
  746. }
  747. }else{
  748. return !!event;
  749. }
  750. }
  751. function autoRun(unit,queue){
  752. var onoff = unit._options.queueEventTrigger;
  753. var args = utils.arg2arr(arguments,2);
  754. if(runEvent.apply(unit,args) !== false){
  755. onoff && runEvent.apply(queue,args);
  756. }
  757. }
  758. function runAddEvent(unit){
  759. runEvent.call(this,'workAdd',this,unit,this);
  760. }
  761. //构建执行单元对象
  762. function getQueueUnit(fn,args,options){
  763. // try{
  764. return new QueueUnit(fn,args,options);
  765. // }catch(e){
  766. // if(utils.isFunction(this.onError)){
  767. // this.onError(e)
  768. // }
  769. // }
  770. }
  771. function onError(err){
  772. if(utils.isFunction(this.onError)){
  773. this.onError.call(this,err)
  774. }
  775. }
  776. function getAddArgs(data,fn,con,each){
  777. var isArray = utils.isArray(data);
  778. var rdata = isArray ? [] : {};
  779. function fill(k){
  780. var args = each ? [].concat([data[k]],[k],[data]) : [].concat(data[k]);
  781. rdata[k] = [fn,args,con];
  782. }
  783. if(isArray){
  784. for(var i=0; i<data.length; i++){
  785. fill(i);
  786. }
  787. }else{
  788. for(var k in data){
  789. fill(k);
  790. }
  791. }
  792. return rdata;
  793. }
  794. function getBatchArgs(array,fn,con){
  795. var baseN = 2,_con,start,jump;
  796. if(utils.isObject(con)){
  797. _con = con;
  798. baseN++;
  799. }
  800. return {
  801. con : _con,
  802. start : arguments[baseN],
  803. jump : arguments[++baseN]
  804. }
  805. }
  806. function AddBatch(data,fn){
  807. var queue = this.queue
  808. ,map = this.map
  809. ,each = this.each
  810. var addArgs;
  811. var args = getBatchArgs.apply(null,arguments)
  812. addArgs = getAddArgs(data,fn,args.con,each)
  813. if(map){
  814. return queue.addProps(addArgs,args.start,args.jump);
  815. }else{
  816. return queue.addArray(addArgs,args.start,args.jump);
  817. }
  818. }
  819. Queue.prototype = {
  820. //获取/设置配置
  821. option: function(name){
  822. if(arguments.length == 1){
  823. return this._options[name];
  824. }else if(arguments.length > 1){
  825. this._options[name] = arguments[1]
  826. }
  827. }
  828. //向队列尾部增加执行项,若队列未启动,暂时不会被执行
  829. ,'push' : function(){
  830. var o = this , unit = getQueueUnit.apply(o,arguments);
  831. o._addItem(unit,false);
  832. return unit.defer.promise;
  833. }
  834. //向队列头部增加执行项,若队列未启动,暂时不会被执行
  835. ,'unshift': function(){
  836. var o = this , unit = getQueueUnit.apply(o,arguments);
  837. o._addItem(unit,true);
  838. return unit.defer.promise;
  839. }
  840. //添加执行项,并会启动队列
  841. ,go: function(){
  842. var o = this , unit = getQueueUnit.apply(o,arguments);
  843. o._addItem(unit,false,true);
  844. return unit.defer.promise;
  845. }
  846. //在队列头部插入并执行项
  847. ,jump: function(){
  848. var o = this , unit = getQueueUnit.apply(o,arguments);
  849. o._addItem(unit,true,true);
  850. return unit.defer.promise;
  851. }
  852. ,add: function(fn,options){//fn,*options*,*start*,*jump*
  853. var o = this, _fun, _i = 1, unitArgs, start, jump, promise;
  854. if(!utils.isFunction(fn)) throw new TypeError("Queues only support function, '" + fn + "' is not function")
  855. _fun = function(){
  856. var defer = _Promise.defer();
  857. fn(defer.resolve,defer.reject);
  858. return defer.promise
  859. }
  860. unitArgs = [_fun]
  861. if(utils.isObject(options)){
  862. unitArgs.push(options);
  863. _i++;
  864. }
  865. start = !!arguments[_i]
  866. jump = !!arguments[_i+1];
  867. promise = jump ? o.unshift.apply(o,unitArgs) : o.push.apply(o,unitArgs);
  868. if(start) o.start();
  869. return promise;
  870. }
  871. ,addArray: function(array,start,jump){
  872. var parrs = [];
  873. var o = this;
  874. for(var i = 0;i<array.length;i++){
  875. +function(){
  876. var _i = i;
  877. var unitArgs = array[_i];
  878. var _p = jump ? o.unshift.apply(o,unitArgs) : o.push.apply(o,unitArgs);
  879. parrs.push(_p);
  880. }()
  881. }
  882. var nextP = _Promise.defer();
  883. _Promise.all(parrs).then(function(data){nextP.resolve(data)},function(err){nextP.reject(err)})
  884. if(start) o.start();
  885. return nextP.promise;
  886. }
  887. ,addProps: function(props,start,jump){
  888. var parrs = {};
  889. var o = this;
  890. for(var k in props){
  891. +function(){
  892. var _k = k;
  893. var unitArgs = props[_k];
  894. var _p = jump ? o.unshift.apply(o,unitArgs) : o.push.apply(o,unitArgs);
  895. parrs[_k] = _p;
  896. }()
  897. }
  898. var nextP = _Promise.defer();
  899. _Promise.allMap(parrs).then(function(data){nextP.resolve(data)},function(err){nextP.reject(err)})
  900. if(start) o.start();
  901. return nextP.promise;
  902. }
  903. ,addLikeArray: function(array,fn,con){
  904. return AddBatch.apply({queue:this},arguments);
  905. }
  906. ,addLikeProps: function(props,fn,con){
  907. return AddBatch.apply({queue:this,map:true},arguments);
  908. }
  909. ,addLikeArrayEach: function(array,fn,con){
  910. return AddBatch.apply({queue:this,each:true},arguments);
  911. }
  912. ,addLikePropsEach: function(array,fn,con){
  913. return AddBatch.apply({queue:this,each:true,map:true},arguments);
  914. }
  915. };
  916. Queue.use = setPromise;
  917. Queue.createUse = use;
  918. return Queue;
  919. };
  920. module.exports = use;
  921. },{"./utils":7,"extend-promise/src/extendClass":4}],7:[function(require,module,exports){
  922. 'use strict';
  923. exports.isArray = function(obj){
  924. return Object.prototype.toString.call(obj) == "[object Array]"
  925. }
  926. exports.isFunction = function(obj){
  927. return typeof obj === "function"
  928. }
  929. exports.isObject = function(obj){
  930. return typeof obj === "object" && obj !== null
  931. }
  932. exports.arg2arr = function(arg,b,s){
  933. return Array.prototype.slice.call(arg,b,s);
  934. }
  935. },{}]},{},[1])