├── index.js ├── create.js ├── .gitignore ├── .gitattributes ├── browser-source ├── promise-queue-plus.es6.js └── promise-queue-plus.js ├── .travis.yml ├── bower.json ├── src ├── utils.js └── queue.js ├── test ├── test_continue.js ├── test_memory.js ├── test_add.js └── mocha_queue.js ├── demo ├── webServer.js ├── demo1.js └── demo2.js ├── package.json ├── gulpfile.js ├── README.md └── dist ├── promise-queue-plus.es6.min.js ├── promise-queue-plus.min.js ├── promise-queue-plus.es6.js └── promise-queue-plus.js /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require("./create")(require("bluebird")); -------------------------------------------------------------------------------- /create.js: -------------------------------------------------------------------------------- 1 | module.exports = require("./src/queue"); 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.out 6 | *.pid 7 | *.gz 8 | 9 | # *.min.js 10 | npm-debug.log 11 | 12 | /.idea/ 13 | /.vscode/ 14 | /typings/ 15 | /node_modules/ 16 | /_temp/ 17 | /coverage/ 18 | 19 | pids 20 | logs 21 | results -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /browser-source/promise-queue-plus.es6.js: -------------------------------------------------------------------------------- 1 | (function (name, factory) { 2 | if (typeof define === 'function' && (define.amd || define.cmd)) { 3 | define([], factory); 4 | } else if (typeof window !== "undefined" || typeof self !== "undefined") { 5 | var global = typeof window !== "undefined" ? window : self; 6 | global[name] = factory(); 7 | } else { 8 | throw new Error('Loading the "' + name + '" module failed!'); 9 | } 10 | }('PromiseQueuePlus', function () { 11 | return require('../src/queue')(Promise); 12 | })); -------------------------------------------------------------------------------- /browser-source/promise-queue-plus.js: -------------------------------------------------------------------------------- 1 | (function (name, factory) { 2 | if (typeof define === 'function' && (define.amd || define.cmd)) { 3 | define([], factory); 4 | } else if (typeof window !== "undefined" || typeof self !== "undefined") { 5 | var global = typeof window !== "undefined" ? window : self; 6 | global[name] = factory(); 7 | } else { 8 | throw new Error('Loading the "' + name + '" module failed!'); 9 | } 10 | }('PromiseQueuePlus', function () { 11 | return require('../src/queue')(require('easy-promise/setTimeout')); 12 | })); -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: 4 | - "0.10" 5 | - "0.12" 6 | - "iojs" 7 | - "4" 8 | - "5" 9 | - "6" 10 | - "7" 11 | - "8" 12 | before_script: 13 | - npm install -g gulp 14 | # - npm install -g istanbul 15 | script: gulp 16 | # Run test script, depending on istanbul install 17 | # - "test -n $(npm -ps ls istanbul) || npm test" 18 | # - "test -z $(npm -ps ls istanbul) || npm run-script test-travis" 19 | 20 | after_script: 21 | - "test -e ./coverage/lcov.info && npm install coveralls@2 && cat ./coverage/lcov.info | coveralls" -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "promise-queue-plus", 3 | "description": "Promise-based queue. Support timeout, retry and so on.", 4 | "main": "dist/promise-queue-plus.js", 5 | "authors": [ 6 | "cnwhy " 7 | ], 8 | "license": "BSD-2-Clause", 9 | "keywords": [ 10 | "Promise", 11 | "queue", 12 | "pool", 13 | "Async", 14 | "Q", 15 | "队列" 16 | ], 17 | "homepage": "https://github.com/cnwhy/promise-queue-plus", 18 | "ignore": [ 19 | "**/.*", 20 | "node_modules", 21 | "bower_components", 22 | "test", 23 | "tests" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | var epc = require("extend-promise/src/extendClass"); 2 | 3 | exports.isArray = function (obj) { 4 | return Object.prototype.toString.call(obj) == "[object Array]"; 5 | } 6 | 7 | exports.isFunction = function (obj) { 8 | return typeof obj === "function"; 9 | } 10 | 11 | exports.isObject = function (obj) { 12 | return typeof obj === "object" && obj !== null 13 | } 14 | 15 | exports.arg2arr = function (arg, b, s) { 16 | return Array.prototype.slice.call(arg, b, s); 17 | } 18 | 19 | exports.toArray = function () { 20 | return Array.prototype.concat.apply([], arguments); 21 | } 22 | 23 | /** 24 | * 将值修整为正整数,0与负数报错 25 | * @param {Number} max 26 | */ 27 | exports.getPositiveInt = function (max) { 28 | var _max = (+max) >> 0; 29 | if (_max >= 1) { 30 | return _max; 31 | } else { 32 | throw new Error('The "max" value is invalid') 33 | } 34 | } 35 | /** 36 | * 扩展Promise 37 | * @param {Promise} Promise 38 | */ 39 | exports.extendPromise = function (Promise) { 40 | return epc(Promise, {}); 41 | } 42 | 43 | exports.runFn2Promise = function (Promise,fn) { 44 | try{ 45 | return Promise.resolve(fn()); 46 | }catch(e){ 47 | return Promise.reject(e); 48 | } 49 | } -------------------------------------------------------------------------------- /test/test_continue.js: -------------------------------------------------------------------------------- 1 | //持续运行测试 2 | var Queue = require('../'); 3 | var q = Queue.Q; 4 | 5 | var leng =50000; 6 | var minN = 5000 7 | 8 | var queue = new Queue(1000) 9 | 10 | //console.log(queue) 11 | function testfun(){ 12 | return function(i){ 13 | var deferred = q.defer(); 14 | setTimeout(function(){ 15 | if(i%2 == 1){ 16 | deferred.reject(i) 17 | }else{ 18 | deferred.resolve(i) 19 | } 20 | //deferred.resolve(i) 21 | },Math.random()*50>>0) 22 | //},Math.random()*30>>0) 23 | return deferred.promise; 24 | } 25 | } 26 | 27 | var n = 0; 28 | var adding = 0; 29 | var data = 0; 30 | function adde(){ 31 | adding = 1; 32 | for(var i = 0; i 3; 17 | } 18 | 19 | function promfun1(i){ 20 | var deferred = q.defer(); 21 | setTimeout(function(){ 22 | deferred.resolve(i) 23 | },sp) 24 | return deferred.promise; 25 | } 26 | 27 | app.use('/',function(req, res, next){ 28 | if(isBusy){ 29 | return next("server busy!") 30 | }else{ 31 | next(); 32 | }; 33 | }) 34 | 35 | app.all('/', function(req, res, next){ 36 | queue.go(promfun1,['Hello Word!']).done(function(data){ 37 | res.end(data) 38 | },function(err){ 39 | next(new Error(err)); 40 | }) 41 | }); 42 | 43 | app.use(function (err, req, res, next) { 44 | console.error('[' + new Date() + ']\n' + err.stack) 45 | var msg = err.stack || err.toString(); 46 | res.status(500).send(msg || "

出错了!

请刷新页面或联系管理员!") 47 | }) 48 | 49 | app.listen(port, function() { 50 | console.log(new Date() + ':start server on port ' + port) 51 | }) -------------------------------------------------------------------------------- /demo/demo1.js: -------------------------------------------------------------------------------- 1 | var Queue = require('../'); 2 | var q = Queue.Promise; //a Promise utils; 3 | 4 | //Realize a queue with a maximum concurrency of 1 5 | var queue1 = new Queue(1,{ 6 | "retry":0 //Number of retries 7 | ,"retryIsJump":false //retry now? 8 | ,"timeout":0 //The timeout period 9 | }); 10 | 11 | //a return promise function 12 | function testfn(i){ 13 | return new Promise(function(resolve,reject){ 14 | setTimeout(function(){ 15 | resolve(i) 16 | },300) 17 | }) 18 | } 19 | var log = function(msg){ console.log(msg); } 20 | 21 | queue1.push(testfn,[1]) //add job (FIFO) 22 | .then(log); 23 | 24 | queue1.push(function(){return 2;}) //The normal function returns a promise according to the Promise / A + rule 25 | .then(log); 26 | 27 | queue1.unshift(testfn,[0]) //add job (LIFO) 28 | .then(log); 29 | 30 | queue1.addLikeArray([3,4],testfn,{'workResolve':log}) //Add multiple jobs with Array, Work done will execute 'workResolve' 31 | .then(log) 32 | 33 | queue1.addLikeProps({'a':5,'b':6,'c':7},testfn,{'workResolve':log}) //Add multiple jobs with Map, 34 | .then(log) 35 | 36 | queue1.add(function(resolve,reject){ 37 | resolve(8) 38 | }).then(log) 39 | 40 | queue1.go(testfn,['go']).then(log) 41 | 42 | 43 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "promise-queue-plus", 3 | "version": "1.2.2", 4 | "description": "Promise-based queue. Support timeout, retry and so on.", 5 | "homepage": "https://github.com/cnwhy/promise-queue-plus", 6 | "main": "index.js", 7 | "files": [ 8 | "index.js", 9 | "create.js", 10 | "src/*", 11 | "dist/*", 12 | "demo/*" 13 | ], 14 | "scripts": { 15 | "test": "mocha --bail --reporter spec test/mocha_*.js", 16 | "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot test/mocha_*.js", 17 | "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec test/mocha_*.js", 18 | "build": "gulp" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/cnwhy/promise-queue-plus.git" 23 | }, 24 | "keywords": [ 25 | "Promise", 26 | "queue", 27 | "pool", 28 | "Async", 29 | "Q", 30 | "队列" 31 | ], 32 | "dependencies": { 33 | "bluebird": "^3.0.0", 34 | "easy-promise": "0.1.0", 35 | "extend-promise": "^0.0.7" 36 | }, 37 | "devDependencies": { 38 | "express": "^4.12.3", 39 | "gulp": "^3.9.1", 40 | "gulp-browserify": "^0.5.1", 41 | "gulp-header": "^2.0.7", 42 | "gulp-istanbul": "^1.1.1", 43 | "gulp-mocha": "^3.0.1", 44 | "gulp-rename": "^1.2.2", 45 | "gulp-uglify": "^3.0.1", 46 | "istanbul": "0.3.15", 47 | "mocha": "^2.5.3", 48 | "q": "*" 49 | }, 50 | "author": { 51 | "name": "cnwhy", 52 | "email": "w.why@163.com" 53 | }, 54 | "license": "BSD-2-Clause" 55 | } 56 | -------------------------------------------------------------------------------- /test/test_memory.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var express = require('express'); 3 | var Queue = require('../'); 4 | var Q = Queue.Q; 5 | var app = express(); 6 | var sp = 1000; 7 | var port = 8899; 8 | var queues = []; 9 | var queue1 = new Queue(100,{queueEnd:function(){console.log('end')}}); 10 | 11 | 12 | function pfun(){ 13 | return function(v){ 14 | return Q.delay(0,v); 15 | } 16 | } 17 | 18 | app.all('/', function(req, res, next){ 19 | return res.end("现有"+queues.length+"个队列 queue1有"+queue1.getLength()+"个队列项"); 20 | }); 21 | 22 | app.all('/add/queue/:n', function(req, res, next){ 23 | var addn = +req.params.n; 24 | var oRAM = process.memoryUsage().rss; 25 | if(addn > 0){ 26 | for(var i = 0; i 0){ 44 | for(var i = 0; i>>>>> 队列开始') 13 | } 14 | function queueEnd(){ 15 | console.log('<<<<<< 队列结束了') 16 | } 17 | function workFinally(){ 18 | console.log('一个执行单元完成') 19 | } 20 | function workAdd(){ 21 | console.log("向队列添加项 ",this.isStart(),this.getLength()) 22 | if(!this.isStart() && this.getLength() >= 5){ //当添加了10个项后,运行队列 23 | console.log(">> 触发自动运行条件") 24 | this.start(); 25 | } 26 | } 27 | 28 | // var q1 = new Queue(1) 29 | // q1.push(function(){return "123"}).then(console.log,console.log); 30 | // q1.start(); 31 | 32 | //new Queue([并行数],) 并行数必须 33 | var queue1 = new Queue(2,{ 34 | "queueStart": queueStart 35 | ,"queueEnd": queueEnd 36 | ,"workResolve": workResolve 37 | ,"workReject": workReject 38 | ,"workFinally": workFinally 39 | ,"retry":0 //出错重试次数 默认0; 40 | ,'workAdd':workAdd //workAdd只会在push/unshift方法添向项时才触发! 41 | }) 42 | 43 | function testfun(i){ 44 | var deferred = q.defer(); 45 | setTimeout(function(){ 46 | if(i%3 == 1 || i == "Qerr"){ 47 | deferred.reject(new Error("err is " + i)) 48 | }else{ 49 | deferred.resolve(i) 50 | } 51 | },1000) 52 | return deferred.promise; 53 | } 54 | 55 | //用push添加项 不会启动队列; 56 | queue1.push(testfun,['Q1']) 57 | queue1.addLikeArrayEach([1,2,3,4,5],function(v,i,arr){ 58 | var deferred = q.defer(); 59 | setTimeout(function(){ 60 | deferred.resolve(i+":"+v); 61 | },500); 62 | return deferred.promise; 63 | },0,1).then(function(data){ 64 | console.log(data); 65 | }) 66 | 67 | setTimeout(function(){ 68 | //用go添加项 将会启动队列; 69 | queue1.go(testfun,['Q2']) 70 | //添加的项返回的是一个promise,所以可以在添加时就定义好“回调” 71 | queue1.go(testfun,['Q3']).then(console.log,console.log) //succ 72 | queue1.go(testfun,['Qerr']).then(console.log,console.log) //err 73 | //也可以这样添加“回调” 74 | var con = { 75 | 'workResolve':function(data){ 76 | console.log(data + '完成!') 77 | } 78 | ,'workReject':function(err){ 79 | console.error(err) 80 | } 81 | } 82 | queue1.go(testfun,['Q4'],con) 83 | //标记此对象不会走队列的成功失败事件. 84 | queue1.go(testfun,['Q5'],{run_queue_event:false}).then(function(data){console.log(data + "不会触发队列初始化时定义的成功/失败方法")}) 85 | 86 | },0) -------------------------------------------------------------------------------- /test/test_add.js: -------------------------------------------------------------------------------- 1 | //不同Promise实现,插入效率测试 2 | var Queue = require('../src/queue'); 3 | var q = require("q"); 4 | var bluebird = require("bluebird") 5 | var p1 = require('extend-promise/Promise/nextTick'); 6 | var p2 = require('extend-promise/Promise/setImmediate'); 7 | var p3 = require('extend-promise/Promise/setTimeout'); 8 | 9 | 10 | if(typeof Promise == 'function'){ 11 | Promise.defer = function () { 12 | var resolve, reject; 13 | var promise = new Promise(function (_resolve, _reject) { 14 | resolve = _resolve; 15 | reject = _reject; 16 | }); 17 | return { 18 | promise: promise, 19 | resolve: resolve, 20 | reject: reject 21 | }; 22 | }; 23 | } 24 | 25 | var Ps = [ 26 | // {P:q,name:"q 模块"}, 27 | {P:Promise,name:"原生Promise"}, 28 | {P:bluebird,name:"bluebird 模块"}, 29 | {P:p1,name:"nextTick"}, 30 | {P:p2,name:"setImmediate"}, 31 | {P:p3,name:"setTimeout"} 32 | ] 33 | 34 | function getTestFun(Pro){ 35 | return function(i,err){ 36 | var deferred = Pro.defer() 37 | setTimeout(function(){ 38 | if(err){ 39 | deferred.reject(err) 40 | }else{ 41 | deferred.resolve(i) 42 | } 43 | },1) 44 | return deferred.promise; 45 | } 46 | } 47 | 48 | var maxl = 50000,bxs = 500; 49 | var _fun = function(){} 50 | function test(P,name){ 51 | var queue = new (Queue(P))(bxs) 52 | console.log('>>>>> '+name+' 测试开始') 53 | def = P.defer(); 54 | var testfun = getTestFun(P) 55 | var d0 = new Date(); 56 | for(var k=0;k=f)&&o.resolve(n)},function(r){l(f)?o.reject(r):0==--i&&o.resolve(n)}),i++};if(a(t)){n=[],0==t.length&&o.resolve(n);for(var e=0;ee._errNo++?c._addItem(e,i,!0,!1):(e.defer.reject(r),j(e,c,"workReject",c,r,c,e)),f())};return 0!=h||d||(d=!0,w.call(c,"queueStart",c,c)),m(function(){return e.fn.apply(u||null,e.regs)}).then(function(r){s()||(e.defer.resolve(r),j(e,c,"workResolve",c,r,c,e),f())},a).then(function(){0>0;if(1<=e)return e;throw new Error('The "max" value is invalid')},t.extendPromise=function(r){return n(r,{})},t.runFn2Promise=function(e,r){try{return e.resolve(r())}catch(r){return e.reject(r)}}},{"extend-promise/src/extendClass":2}]},{},[1]); -------------------------------------------------------------------------------- /dist/promise-queue-plus.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * promise-queue-plus v1.2.2 3 | * Homepage https://github.com/cnwhy/promise-queue-plus 4 | * License BSD-2-Clause 5 | */ 6 | !function o(i,u,s){function f(r,t){if(!u[r]){if(!i[r]){var e="function"==typeof require&&require;if(!t&&e)return e(r,!0);if(c)return c(r,!0);throw new Error("Cannot find module '"+r+"'")}var n=u[r]={exports:{}};i[r][0].call(n.exports,function(t){var e=i[r][1][t];return f(e||t)},n,n.exports,o,i,u,s)}return u[r].exports}for(var c="function"==typeof require&&require,t=0;t=f)&&o.resolve(n)},function(t){l(f)?o.reject(t):0==--i&&o.resolve(n)}),i++};if(c(r)){n=[],0==r.length&&o.resolve(n);for(var e=0;ee._errNo++?a._addItem(e,i,!0,!1):(e.defer.reject(t),g(e,a,"workReject",a,t,a,e)),f())};return 0!=h||v||(v=!0,w.call(a,"queueStart",a,a)),m(function(){return e.fn.apply(u||null,e.regs)}).then(function(t){s()||(e.defer.resolve(t),g(e,a,"workResolve",a,t,a,e),f())},c).then(function(){0>0;if(1<=e)return e;throw new Error('The "max" value is invalid')},r.extendPromise=function(t){return n(t,{})},r.runFn2Promise=function(e,t){try{return e.resolve(t())}catch(t){return e.reject(t)}}},{"extend-promise/src/extendClass":4}]},{},[1]); -------------------------------------------------------------------------------- /src/queue.js: -------------------------------------------------------------------------------- 1 | var utils = require("./utils"); 2 | 3 | function use(Promise){ 4 | var _Promise; 5 | setPromise(Promise); 6 | 7 | var ONERROR = function(err){ 8 | console.error(err); 9 | }; 10 | 11 | /** 12 | * 运行函数,使其始终返回promise对像 13 | * @param {function} fn 14 | * @return {Promise} 15 | */ 16 | var runFn = function(fn){ 17 | return utils.runFn2Promise(_Promise,fn); 18 | } 19 | 20 | /** 21 | * 设置内部使用的Promise 22 | * @param {Promise} Promise 23 | */ 24 | function setPromise(Promise){ 25 | _Promise = Queue.Q = Queue.Promise = utils.extendPromise(Promise); 26 | }; 27 | 28 | /** 29 | * 队列类 30 | * @param {Number} max 队列最大并行数 31 | * @param {Number} options 队列其他配置 32 | */ 33 | function Queue(max,options) { 34 | if (!(this instanceof Queue)) { 35 | return new Queue(max,options); 36 | } 37 | var self = this; 38 | var def = { 39 | "queueStart" : null //队列开始 40 | ,"queueEnd" : null //队列完成 41 | ,"workAdd" : null //有执行项添加进执行单元后执行 42 | ,"workResolve": null //成功 43 | ,"workReject" : null //失败 44 | ,"workFinally": null //一个执行单元结束后 45 | ,"retry" : 0 //执行单元出错重试次数 46 | ,"retryIsJump": false //重试模式 false:搁置执行(插入队列尾部重试),true:优先执行 (插入队列头部重试) 47 | ,"timeout" : 0 //执行单元超时时间(毫秒) 48 | ,"autoRun" : false 49 | } 50 | 51 | var _queue = []; 52 | var _max = utils.getPositiveInt(max); //最大并行数 53 | var _runCount = 0; //当前并行数 54 | var _isStart = false; //已运行 55 | var _isStop = 0; //是否暂停 56 | this._options = def 57 | this.onError = ONERROR; 58 | 59 | if(utils.isObject(options)){ 60 | for(var i in options){ 61 | if(def.hasOwnProperty(i)) def[i] = options[i] 62 | } 63 | } 64 | 65 | //最大并行数 66 | this.getMax = function(){ 67 | return _max; 68 | } 69 | this.setMax = function(max){ 70 | _max = utils.getPositiveInt(max); 71 | if(!_isStop && _runCount) self.start(); 72 | } 73 | //正在排队的项数 74 | this.getLength = function(){ 75 | return _queue.length; 76 | } 77 | //正在运行的项数 78 | this.getRunCount = function(){ 79 | return _runCount; 80 | } 81 | //队列是否已开始运行 82 | this.isStart = function(){ 83 | return !!_isStart; 84 | } 85 | 86 | /** 87 | * 向队列插入执行单元 88 | * @param {queueUnit} unit 执行单元对像 89 | * @param {bool} stack 是否以栈模式(后进先出)插入 90 | * @param {bool} start 是否启动队列 91 | * @param {bool} noAdd 是否调用队列workAdd方法 (防止重试模式 workAdd 调用多次) 92 | */ 93 | this._addItem = function(unit,stack,start,noAdd){ 94 | if(!(unit instanceof QueueUnit)) throw new TypeError('"unit" is not QueueUnit') 95 | if(stack){ 96 | _queue.unshift(unit); 97 | }else{ 98 | _queue.push(unit); 99 | } 100 | noAdd || runAddEvent.call(self,unit); 101 | if(start || self._options.autoRun){ 102 | self.start(); 103 | }else{ 104 | _isStart && queueRun(); 105 | } 106 | } 107 | 108 | //执行下一项 109 | function next(){ 110 | if(_runCount < _max && !_isStop && _queue.length > 0){ 111 | var unit = _queue.shift() 112 | //if(unit){ 113 | var xc_timeout 114 | ,_mark=0 115 | var timeout = +getOption('timeout',unit,self) 116 | ,retryNo = getOption('retry',unit,self) 117 | ,retryType = getOption('retryIsJump',unit,self) 118 | ,_self = unit._options.self 119 | var fix = function(){ 120 | if(xc_timeout) clearTimeout(xc_timeout) 121 | xc_timeout = 0; 122 | if(_mark++) return true; 123 | _runCount--; 124 | } 125 | 126 | 127 | 128 | var afinally = function(){ 129 | autoRun(unit,self,'workFinally',self,self,unit) 130 | // if(runEvent.call(unit,'workFinally',self,self,unit) !== false){ 131 | // onoff && runEvent.call(self,'workFinally',self,self,unit); 132 | // } 133 | } 134 | 135 | var issucc = function(data){ 136 | if(fix()) return; 137 | unit.defer.resolve(data); //通知执行单元,成功 138 | autoRun(unit,self,'workResolve',self,data,self,unit) 139 | // if(runEvent.call(unit,'workResolve',self,data,self,unit) !== false){ 140 | // onoff && runEvent.call(self,'workResolve',self,data,self,unit); 141 | // } 142 | afinally(); 143 | } 144 | 145 | var iserr = function(err){ 146 | if(fix()) return; 147 | if(retryNo > unit._errNo++){ 148 | self._addItem(unit,retryType,true,false) 149 | }else{ 150 | unit.defer.reject(err); //通知执行单元,失败 151 | autoRun(unit,self,'workReject',self,err,self,unit) 152 | // if(runEvent.call(unit,'workReject',self,err,self,unit) !== false){ 153 | // onoff && runEvent.call(self,'workReject',self,err,self,unit); 154 | // } 155 | } 156 | afinally(); 157 | }; 158 | 159 | //队列开始执行事件 160 | if(_runCount == 0 && !_isStart){ 161 | _isStart = true; 162 | runEvent.call(self,'queueStart',self,self); 163 | } 164 | 165 | var nextp = runFn(function(){ 166 | return unit.fn.apply((_self || null),unit.regs) 167 | }).then(issucc,iserr).then(function(){ 168 | if(_queue.length>0){ 169 | queueRun(); 170 | }else if(_runCount == 0 && _isStart){//队列结束执行事件 171 | _isStart = false; 172 | runEvent.call(self,'queueEnd',self,self); 173 | } 174 | }); 175 | _runCount += 1; 176 | //nextp.then(defer.resolve,defer.reject) 177 | if(timeout > 0){ 178 | xc_timeout = setTimeout(function(){ 179 | iserr("timeout") 180 | },timeout) 181 | } 182 | //return; 183 | //} 184 | return; 185 | } 186 | return true; 187 | } 188 | 189 | function queueRun(){ 190 | while(!next()){} 191 | // if(_isStop) return; 192 | // do{ 193 | // next(); 194 | // }while(_queue.length && _runCount < _max) 195 | } 196 | /**队列控制**/ 197 | 198 | //开始执行队列 199 | this.start = function(){ 200 | _isStop = 0; 201 | queueRun(); 202 | } 203 | 204 | this.stop = function(){ 205 | //console.log('on stop') 206 | _isStop = 1; 207 | } 208 | 209 | //清空执行队列 210 | this.clear = function(err){ 211 | while(_queue.length){ 212 | var unit = _queue.shift(); 213 | unit.defer.reject(err); 214 | } 215 | } 216 | } 217 | 218 | /** 219 | * 队列执行单元类 220 | * @param {Function} fn 运行函数 221 | * @param {Array} args 运行函数的参数,可省略 222 | * @param {Object} options 其他配置 223 | */ 224 | function QueueUnit(fn, args, options){ 225 | var def = { 226 | 'workResolve' : true 227 | ,'workReject' : true 228 | ,'workFinally' : true 229 | ,'queueEventTrigger' : true 230 | ,'regs':[] 231 | ,'self':null 232 | } 233 | var oNames = [ 234 | 'workResolve' //是否执行队列workResolve事件 235 | ,'workReject' //是否执行队列workReject事件 236 | ,'workFinally' //是否执行队列workFinally事件 237 | ,'queueEventTrigger' //队列事件开关 238 | ,'retry' //重试次数 239 | ,'retryIsJump' //重试模式 240 | ,'timeout' //超时 241 | ,'self' //运行函数self 242 | ]; 243 | var oi = 1; 244 | if(!utils.isFunction(fn)){ 245 | throw new TypeError("Queues only support function, '" + fn + "' is not function") 246 | } 247 | this.fn = fn; 248 | this._errNo = 0; 249 | this.defer = _Promise.defer(); 250 | if(utils.isArray(args)){ 251 | this.regs = args; 252 | oi++; 253 | } 254 | 255 | function inOptions(name){ 256 | for(var i = 0; i 1){ 377 | this._options[name] = arguments[1] 378 | } 379 | } 380 | 381 | //向队列尾部增加执行项,若队列未启动,暂时不会被执行 382 | ,'push' : function(){ 383 | var o = this , unit = getQueueUnit.apply(o,arguments); 384 | o._addItem(unit,false); 385 | return unit.defer.promise; 386 | } 387 | //向队列头部增加执行项,若队列未启动,暂时不会被执行 388 | ,'unshift': function(){ 389 | var o = this , unit = getQueueUnit.apply(o,arguments); 390 | o._addItem(unit,true); 391 | return unit.defer.promise; 392 | } 393 | //添加执行项,并会启动队列 394 | ,go: function(){ 395 | var o = this , unit = getQueueUnit.apply(o,arguments); 396 | o._addItem(unit,false,true); 397 | return unit.defer.promise; 398 | } 399 | //在队列头部插入并执行项 400 | ,jump: function(){ 401 | var o = this , unit = getQueueUnit.apply(o,arguments); 402 | o._addItem(unit,true,true); 403 | return unit.defer.promise; 404 | } 405 | ,add: function(fn,options){//fn,*options*,*start*,*jump* 406 | var o = this, _fun, _i = 1, unitArgs, start, jump, promise; 407 | if(!utils.isFunction(fn)) throw new TypeError("Queues only support function, '" + fn + "' is not function") 408 | _fun = function(){ 409 | var defer = _Promise.defer(); 410 | fn(defer.resolve,defer.reject); 411 | return defer.promise 412 | } 413 | unitArgs = [_fun] 414 | if(utils.isObject(options)){ 415 | unitArgs.push(options); 416 | _i++; 417 | } 418 | start = !!arguments[_i] 419 | jump = !!arguments[_i+1]; 420 | promise = jump ? o.unshift.apply(o,unitArgs) : o.push.apply(o,unitArgs); 421 | if(start) o.start(); 422 | return promise; 423 | } 424 | ,addArray: function(array,start,jump){ 425 | var parrs = []; 426 | var o = this; 427 | for(var i = 0;i 0 ? +count : 0; 111 | } 112 | return function(promises) { 113 | var defer = QClass.defer(); 114 | var data,_tempI = 0; 115 | var fillData = function(i){ 116 | var _p = promises[i]; 117 | QClass.resolve(_p).then(function(d) { 118 | if(typeof count != 'undefined'){ 119 | data.push(d); 120 | }else{ 121 | data[i] = d; 122 | } 123 | if (--_tempI == 0 || (!map && count && data.length>=count)) { 124 | defer.resolve(data); 125 | } 126 | }, function(err) { 127 | if (isEmpty(count)) { 128 | defer.reject(err); 129 | }else if(--_tempI == 0){ 130 | defer.resolve(data); 131 | } 132 | }) 133 | _tempI++; 134 | } 135 | if(isArray(promises)){ 136 | data = []; 137 | if(promises.length == 0){defer.resolve(data)}; 138 | for(var i = 0; i= 0 ? +count : 0; 168 | return getall(false,count)(proArr) 169 | } 170 | } 171 | 172 | //map 173 | if(asbind("map")){ 174 | QClass.map = function(data,mapfun,options){ 175 | var defer = QClass.defer(); 176 | var promiseArr = []; 177 | var concurrency = options ? +options.concurrency : 0 178 | //无并发控制 179 | if(concurrency == 0 || concurrency != concurrency){ 180 | for(var i in data){ 181 | promiseArr.push(mapfun(data[i],i,data)); 182 | } 183 | QClass.all(promiseArr).then(defer.resolve,defer.reject) 184 | return defer.promise; 185 | } 186 | var k = 0; 187 | var keys = (function(){ 188 | var ks = []; 189 | for(var k in data){ 190 | ks.push(k); 191 | } 192 | return ks; 193 | })(); 194 | function next(){ 195 | if(k0 && k 0){ 423 | var unit = _queue.shift() 424 | //if(unit){ 425 | var xc_timeout 426 | ,_mark=0 427 | var timeout = +getOption('timeout',unit,self) 428 | ,retryNo = getOption('retry',unit,self) 429 | ,retryType = getOption('retryIsJump',unit,self) 430 | ,_self = unit._options.self 431 | var fix = function(){ 432 | if(xc_timeout) clearTimeout(xc_timeout) 433 | xc_timeout = 0; 434 | if(_mark++) return true; 435 | _runCount--; 436 | } 437 | 438 | 439 | 440 | var afinally = function(){ 441 | autoRun(unit,self,'workFinally',self,self,unit) 442 | // if(runEvent.call(unit,'workFinally',self,self,unit) !== false){ 443 | // onoff && runEvent.call(self,'workFinally',self,self,unit); 444 | // } 445 | } 446 | 447 | var issucc = function(data){ 448 | if(fix()) return; 449 | unit.defer.resolve(data); //通知执行单元,成功 450 | autoRun(unit,self,'workResolve',self,data,self,unit) 451 | // if(runEvent.call(unit,'workResolve',self,data,self,unit) !== false){ 452 | // onoff && runEvent.call(self,'workResolve',self,data,self,unit); 453 | // } 454 | afinally(); 455 | } 456 | 457 | var iserr = function(err){ 458 | if(fix()) return; 459 | if(retryNo > unit._errNo++){ 460 | self._addItem(unit,retryType,true,false) 461 | }else{ 462 | unit.defer.reject(err); //通知执行单元,失败 463 | autoRun(unit,self,'workReject',self,err,self,unit) 464 | // if(runEvent.call(unit,'workReject',self,err,self,unit) !== false){ 465 | // onoff && runEvent.call(self,'workReject',self,err,self,unit); 466 | // } 467 | } 468 | afinally(); 469 | }; 470 | 471 | //队列开始执行事件 472 | if(_runCount == 0 && !_isStart){ 473 | _isStart = true; 474 | runEvent.call(self,'queueStart',self,self); 475 | } 476 | 477 | var nextp = runFn(function(){ 478 | return unit.fn.apply((_self || null),unit.regs) 479 | }).then(issucc,iserr).then(function(){ 480 | if(_queue.length>0){ 481 | queueRun(); 482 | }else if(_runCount == 0 && _isStart){//队列结束执行事件 483 | _isStart = false; 484 | runEvent.call(self,'queueEnd',self,self); 485 | } 486 | }); 487 | _runCount += 1; 488 | //nextp.then(defer.resolve,defer.reject) 489 | if(timeout > 0){ 490 | xc_timeout = setTimeout(function(){ 491 | iserr("timeout") 492 | },timeout) 493 | } 494 | //return; 495 | //} 496 | return; 497 | } 498 | return true; 499 | } 500 | 501 | function queueRun(){ 502 | while(!next()){} 503 | // if(_isStop) return; 504 | // do{ 505 | // next(); 506 | // }while(_queue.length && _runCount < _max) 507 | } 508 | /**队列控制**/ 509 | 510 | //开始执行队列 511 | this.start = function(){ 512 | _isStop = 0; 513 | queueRun(); 514 | } 515 | 516 | this.stop = function(){ 517 | //console.log('on stop') 518 | _isStop = 1; 519 | } 520 | 521 | //清空执行队列 522 | this.clear = function(err){ 523 | while(_queue.length){ 524 | var unit = _queue.shift(); 525 | unit.defer.reject(err); 526 | } 527 | } 528 | } 529 | 530 | /** 531 | * 队列执行单元类 532 | * @param {Function} fn 运行函数 533 | * @param {Array} args 运行函数的参数,可省略 534 | * @param {Object} options 其他配置 535 | */ 536 | function QueueUnit(fn, args, options){ 537 | var def = { 538 | 'workResolve' : true 539 | ,'workReject' : true 540 | ,'workFinally' : true 541 | ,'queueEventTrigger' : true 542 | ,'regs':[] 543 | ,'self':null 544 | } 545 | var oNames = [ 546 | 'workResolve' //是否执行队列workResolve事件 547 | ,'workReject' //是否执行队列workReject事件 548 | ,'workFinally' //是否执行队列workFinally事件 549 | ,'queueEventTrigger' //队列事件开关 550 | ,'retry' //重试次数 551 | ,'retryIsJump' //重试模式 552 | ,'timeout' //超时 553 | ,'self' //运行函数self 554 | ]; 555 | var oi = 1; 556 | if(!utils.isFunction(fn)){ 557 | throw new TypeError("Queues only support function, '" + fn + "' is not function") 558 | } 559 | this.fn = fn; 560 | this._errNo = 0; 561 | this.defer = _Promise.defer(); 562 | if(utils.isArray(args)){ 563 | this.regs = args; 564 | oi++; 565 | } 566 | 567 | function inOptions(name){ 568 | for(var i = 0; i 1){ 689 | this._options[name] = arguments[1] 690 | } 691 | } 692 | 693 | //向队列尾部增加执行项,若队列未启动,暂时不会被执行 694 | ,'push' : function(){ 695 | var o = this , unit = getQueueUnit.apply(o,arguments); 696 | o._addItem(unit,false); 697 | return unit.defer.promise; 698 | } 699 | //向队列头部增加执行项,若队列未启动,暂时不会被执行 700 | ,'unshift': function(){ 701 | var o = this , unit = getQueueUnit.apply(o,arguments); 702 | o._addItem(unit,true); 703 | return unit.defer.promise; 704 | } 705 | //添加执行项,并会启动队列 706 | ,go: function(){ 707 | var o = this , unit = getQueueUnit.apply(o,arguments); 708 | o._addItem(unit,false,true); 709 | return unit.defer.promise; 710 | } 711 | //在队列头部插入并执行项 712 | ,jump: function(){ 713 | var o = this , unit = getQueueUnit.apply(o,arguments); 714 | o._addItem(unit,true,true); 715 | return unit.defer.promise; 716 | } 717 | ,add: function(fn,options){//fn,*options*,*start*,*jump* 718 | var o = this, _fun, _i = 1, unitArgs, start, jump, promise; 719 | if(!utils.isFunction(fn)) throw new TypeError("Queues only support function, '" + fn + "' is not function") 720 | _fun = function(){ 721 | var defer = _Promise.defer(); 722 | fn(defer.resolve,defer.reject); 723 | return defer.promise 724 | } 725 | unitArgs = [_fun] 726 | if(utils.isObject(options)){ 727 | unitArgs.push(options); 728 | _i++; 729 | } 730 | start = !!arguments[_i] 731 | jump = !!arguments[_i+1]; 732 | promise = jump ? o.unshift.apply(o,unitArgs) : o.push.apply(o,unitArgs); 733 | if(start) o.start(); 734 | return promise; 735 | } 736 | ,addArray: function(array,start,jump){ 737 | var parrs = []; 738 | var o = this; 739 | for(var i = 0;i> 0; 817 | if (_max >= 1) { 818 | return _max; 819 | } else { 820 | throw new Error('The "max" value is invalid') 821 | } 822 | } 823 | /** 824 | * 扩展Promise 825 | * @param {Promise} Promise 826 | */ 827 | exports.extendPromise = function (Promise) { 828 | return epc(Promise, {}); 829 | } 830 | 831 | exports.runFn2Promise = function (Promise,fn) { 832 | try{ 833 | return Promise.resolve(fn()); 834 | }catch(e){ 835 | return Promise.reject(e); 836 | } 837 | } 838 | },{"extend-promise/src/extendClass":2}]},{},[1]) -------------------------------------------------------------------------------- /dist/promise-queue-plus.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * promise-queue-plus v1.2.2 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 0 ? +count : 0; 316 | } 317 | return function(promises) { 318 | var defer = QClass.defer(); 319 | var data,_tempI = 0; 320 | var fillData = function(i){ 321 | var _p = promises[i]; 322 | QClass.resolve(_p).then(function(d) { 323 | if(typeof count != 'undefined'){ 324 | data.push(d); 325 | }else{ 326 | data[i] = d; 327 | } 328 | if (--_tempI == 0 || (!map && count && data.length>=count)) { 329 | defer.resolve(data); 330 | } 331 | }, function(err) { 332 | if (isEmpty(count)) { 333 | defer.reject(err); 334 | }else if(--_tempI == 0){ 335 | defer.resolve(data); 336 | } 337 | }) 338 | _tempI++; 339 | } 340 | if(isArray(promises)){ 341 | data = []; 342 | if(promises.length == 0){defer.resolve(data)}; 343 | for(var i = 0; i= 0 ? +count : 0; 373 | return getall(false,count)(proArr) 374 | } 375 | } 376 | 377 | //map 378 | if(asbind("map")){ 379 | QClass.map = function(data,mapfun,options){ 380 | var defer = QClass.defer(); 381 | var promiseArr = []; 382 | var concurrency = options ? +options.concurrency : 0 383 | //无并发控制 384 | if(concurrency == 0 || concurrency != concurrency){ 385 | for(var i in data){ 386 | promiseArr.push(mapfun(data[i],i,data)); 387 | } 388 | QClass.all(promiseArr).then(defer.resolve,defer.reject) 389 | return defer.promise; 390 | } 391 | var k = 0; 392 | var keys = (function(){ 393 | var ks = []; 394 | for(var k in data){ 395 | ks.push(k); 396 | } 397 | return ks; 398 | })(); 399 | function next(){ 400 | if(k0 && k 0){ 628 | var unit = _queue.shift() 629 | //if(unit){ 630 | var xc_timeout 631 | ,_mark=0 632 | var timeout = +getOption('timeout',unit,self) 633 | ,retryNo = getOption('retry',unit,self) 634 | ,retryType = getOption('retryIsJump',unit,self) 635 | ,_self = unit._options.self 636 | var fix = function(){ 637 | if(xc_timeout) clearTimeout(xc_timeout) 638 | xc_timeout = 0; 639 | if(_mark++) return true; 640 | _runCount--; 641 | } 642 | 643 | 644 | 645 | var afinally = function(){ 646 | autoRun(unit,self,'workFinally',self,self,unit) 647 | // if(runEvent.call(unit,'workFinally',self,self,unit) !== false){ 648 | // onoff && runEvent.call(self,'workFinally',self,self,unit); 649 | // } 650 | } 651 | 652 | var issucc = function(data){ 653 | if(fix()) return; 654 | unit.defer.resolve(data); //通知执行单元,成功 655 | autoRun(unit,self,'workResolve',self,data,self,unit) 656 | // if(runEvent.call(unit,'workResolve',self,data,self,unit) !== false){ 657 | // onoff && runEvent.call(self,'workResolve',self,data,self,unit); 658 | // } 659 | afinally(); 660 | } 661 | 662 | var iserr = function(err){ 663 | if(fix()) return; 664 | if(retryNo > unit._errNo++){ 665 | self._addItem(unit,retryType,true,false) 666 | }else{ 667 | unit.defer.reject(err); //通知执行单元,失败 668 | autoRun(unit,self,'workReject',self,err,self,unit) 669 | // if(runEvent.call(unit,'workReject',self,err,self,unit) !== false){ 670 | // onoff && runEvent.call(self,'workReject',self,err,self,unit); 671 | // } 672 | } 673 | afinally(); 674 | }; 675 | 676 | //队列开始执行事件 677 | if(_runCount == 0 && !_isStart){ 678 | _isStart = true; 679 | runEvent.call(self,'queueStart',self,self); 680 | } 681 | 682 | var nextp = runFn(function(){ 683 | return unit.fn.apply((_self || null),unit.regs) 684 | }).then(issucc,iserr).then(function(){ 685 | if(_queue.length>0){ 686 | queueRun(); 687 | }else if(_runCount == 0 && _isStart){//队列结束执行事件 688 | _isStart = false; 689 | runEvent.call(self,'queueEnd',self,self); 690 | } 691 | }); 692 | _runCount += 1; 693 | //nextp.then(defer.resolve,defer.reject) 694 | if(timeout > 0){ 695 | xc_timeout = setTimeout(function(){ 696 | iserr("timeout") 697 | },timeout) 698 | } 699 | //return; 700 | //} 701 | return; 702 | } 703 | return true; 704 | } 705 | 706 | function queueRun(){ 707 | while(!next()){} 708 | // if(_isStop) return; 709 | // do{ 710 | // next(); 711 | // }while(_queue.length && _runCount < _max) 712 | } 713 | /**队列控制**/ 714 | 715 | //开始执行队列 716 | this.start = function(){ 717 | _isStop = 0; 718 | queueRun(); 719 | } 720 | 721 | this.stop = function(){ 722 | //console.log('on stop') 723 | _isStop = 1; 724 | } 725 | 726 | //清空执行队列 727 | this.clear = function(err){ 728 | while(_queue.length){ 729 | var unit = _queue.shift(); 730 | unit.defer.reject(err); 731 | } 732 | } 733 | } 734 | 735 | /** 736 | * 队列执行单元类 737 | * @param {Function} fn 运行函数 738 | * @param {Array} args 运行函数的参数,可省略 739 | * @param {Object} options 其他配置 740 | */ 741 | function QueueUnit(fn, args, options){ 742 | var def = { 743 | 'workResolve' : true 744 | ,'workReject' : true 745 | ,'workFinally' : true 746 | ,'queueEventTrigger' : true 747 | ,'regs':[] 748 | ,'self':null 749 | } 750 | var oNames = [ 751 | 'workResolve' //是否执行队列workResolve事件 752 | ,'workReject' //是否执行队列workReject事件 753 | ,'workFinally' //是否执行队列workFinally事件 754 | ,'queueEventTrigger' //队列事件开关 755 | ,'retry' //重试次数 756 | ,'retryIsJump' //重试模式 757 | ,'timeout' //超时 758 | ,'self' //运行函数self 759 | ]; 760 | var oi = 1; 761 | if(!utils.isFunction(fn)){ 762 | throw new TypeError("Queues only support function, '" + fn + "' is not function") 763 | } 764 | this.fn = fn; 765 | this._errNo = 0; 766 | this.defer = _Promise.defer(); 767 | if(utils.isArray(args)){ 768 | this.regs = args; 769 | oi++; 770 | } 771 | 772 | function inOptions(name){ 773 | for(var i = 0; i 1){ 894 | this._options[name] = arguments[1] 895 | } 896 | } 897 | 898 | //向队列尾部增加执行项,若队列未启动,暂时不会被执行 899 | ,'push' : function(){ 900 | var o = this , unit = getQueueUnit.apply(o,arguments); 901 | o._addItem(unit,false); 902 | return unit.defer.promise; 903 | } 904 | //向队列头部增加执行项,若队列未启动,暂时不会被执行 905 | ,'unshift': function(){ 906 | var o = this , unit = getQueueUnit.apply(o,arguments); 907 | o._addItem(unit,true); 908 | return unit.defer.promise; 909 | } 910 | //添加执行项,并会启动队列 911 | ,go: function(){ 912 | var o = this , unit = getQueueUnit.apply(o,arguments); 913 | o._addItem(unit,false,true); 914 | return unit.defer.promise; 915 | } 916 | //在队列头部插入并执行项 917 | ,jump: function(){ 918 | var o = this , unit = getQueueUnit.apply(o,arguments); 919 | o._addItem(unit,true,true); 920 | return unit.defer.promise; 921 | } 922 | ,add: function(fn,options){//fn,*options*,*start*,*jump* 923 | var o = this, _fun, _i = 1, unitArgs, start, jump, promise; 924 | if(!utils.isFunction(fn)) throw new TypeError("Queues only support function, '" + fn + "' is not function") 925 | _fun = function(){ 926 | var defer = _Promise.defer(); 927 | fn(defer.resolve,defer.reject); 928 | return defer.promise 929 | } 930 | unitArgs = [_fun] 931 | if(utils.isObject(options)){ 932 | unitArgs.push(options); 933 | _i++; 934 | } 935 | start = !!arguments[_i] 936 | jump = !!arguments[_i+1]; 937 | promise = jump ? o.unshift.apply(o,unitArgs) : o.push.apply(o,unitArgs); 938 | if(start) o.start(); 939 | return promise; 940 | } 941 | ,addArray: function(array,start,jump){ 942 | var parrs = []; 943 | var o = this; 944 | for(var i = 0;i> 0; 1022 | if (_max >= 1) { 1023 | return _max; 1024 | } else { 1025 | throw new Error('The "max" value is invalid') 1026 | } 1027 | } 1028 | /** 1029 | * 扩展Promise 1030 | * @param {Promise} Promise 1031 | */ 1032 | exports.extendPromise = function (Promise) { 1033 | return epc(Promise, {}); 1034 | } 1035 | 1036 | exports.runFn2Promise = function (Promise,fn) { 1037 | try{ 1038 | return Promise.resolve(fn()); 1039 | }catch(e){ 1040 | return Promise.reject(e); 1041 | } 1042 | } 1043 | },{"extend-promise/src/extendClass":4}]},{},[1]) -------------------------------------------------------------------------------- /test/mocha_queue.js: -------------------------------------------------------------------------------- 1 | var assert = require("assert"); 2 | var Queue = require('../index'); 3 | var Q = Queue.Q; 4 | var MAXTIME = 30 5 | var NULLFUN = function () {}; 6 | 7 | //同步函数 8 | function fun1(i, err) { 9 | var deferred = Q.defer(); 10 | if (err) { 11 | deferred.reject(err) 12 | } else { 13 | deferred.resolve(i) 14 | } 15 | return deferred.promise; 16 | } 17 | 18 | //异步函数 19 | function fun2(i, err) { 20 | var deferred = Q.defer(); 21 | setTimeout(function () { 22 | if (err) { 23 | deferred.reject(err) 24 | } else { 25 | deferred.resolve(i) 26 | } 27 | }, MAXTIME) 28 | //},(Math.random() * MAXTIME)>>0) 29 | return deferred.promise; 30 | } 31 | 32 | function fun2_p(i, err) { 33 | return function (resolve, reject) { 34 | setTimeout(function () { 35 | if (err) { 36 | reject(err) 37 | } else { 38 | resolve(i) 39 | } 40 | }, MAXTIME) 41 | } 42 | } 43 | 44 | 45 | function fun3() { 46 | return fun2.apply(null, arguments) 47 | } 48 | 49 | function fun4(v, i, all) { 50 | if (all[i] !== v) throw ("执行参数错误!"); 51 | return fun2.apply(null, [].concat(v)) 52 | } 53 | 54 | function ADD(queue, type, start) { 55 | type = type || ""; 56 | start = start || 0; 57 | var ts = type.split("|"); 58 | var err = start <= 0, 59 | succ = start >= 0; 60 | var nostart; 61 | var i = 1; 62 | if (type == "nostart") { 63 | nostart = 1; 64 | type = ""; 65 | } 66 | if (!type || ~ts.indexOf('push')) { 67 | succ && queue.push(fun2, [i++]); 68 | err && queue.push(fun2, [i++, "push err"]).then(null, NULLFUN); 69 | } 70 | if (!type || ~ts.indexOf('unshift')) { 71 | succ && queue.unshift(fun2, [i++]); 72 | err && queue.unshift(fun2, [i++, "unshift err"]).then(null, NULLFUN); 73 | } 74 | if (!nostart) { 75 | if (!type || ~ts.indexOf('go')) { 76 | succ && queue.go(fun2, [i++]); 77 | err && queue.go(fun2, [i++, "go err"]).then(null, NULLFUN); 78 | } 79 | if (!type || ~ts.indexOf('jump')) { 80 | succ && queue.jump(fun2, [i++]); 81 | err && queue.jump(fun2, [i++, "jump err"]).then(null, NULLFUN); 82 | } 83 | } 84 | if (!type || ~ts.indexOf('addArray')) { 85 | var arr = []; 86 | succ && arr.push([fun2, [i++]]); 87 | err && arr.push([fun2, [i++, "addArray err"]]); 88 | queue.addArray(arr).then(null, NULLFUN); 89 | } 90 | if (!type || ~ts.indexOf('addLikeArray')) { 91 | var arr = []; 92 | succ && arr.push(i++); 93 | err && arr.push([i++, "addLikeArray err"]); 94 | queue.addLikeArray(arr, fun3).then(null, NULLFUN); 95 | } 96 | if (!type || ~ts.indexOf('addLikeArrayEach')) { 97 | var arr = []; 98 | succ && arr.push(i++); 99 | err && arr.push([i++, "addLikeArrayEach err"]); 100 | var fun_temp = function (v, i, arr) { 101 | return fun2.apply(null, [].concat(v)); 102 | } 103 | queue.addLikePropsEach(arr, fun_temp) 104 | } 105 | if (!type || ~ts.indexOf('addLikePropsEach')) { 106 | var map = {}; 107 | succ && (map.a = i++); 108 | err && (map.b = [i++, "addLikePropsEach err"]); 109 | var fun_temp = function (v, k, map) { 110 | return fun2.apply(null, [].concat(v)); 111 | } 112 | queue.addLikePropsEach(map, fun_temp) 113 | } 114 | return queue; 115 | } 116 | 117 | var succ = function (k, done, xc) { 118 | return function (data) { 119 | xc && clearTimeout(xc) 120 | if (data !== k) return done("返回参数错误"); 121 | done(); 122 | } 123 | }, 124 | err = function (done, xc, err) { 125 | return function (err) { 126 | xc && clearTimeout(xc) 127 | done(err || "调用错误"); 128 | } 129 | }, 130 | timeout_succ = function (done, c) { 131 | c = c ? c : 1; 132 | return setTimeout(function () { 133 | done(); 134 | }, (MAXTIME + 100) * c) 135 | }, 136 | timeout_err = function (done, errmsg, c) { 137 | c = c ? c : 1; 138 | return setTimeout(function () { 139 | done(errmsg); 140 | }, (MAXTIME + 100) * c) 141 | } 142 | 143 | var addnoFun = function (queue, type) { 144 | var noFuns = [null, undefined, NaN, 0, 1, "", "a", { 145 | a: 1 146 | }, 147 | [1, 2, 3], /abc/ 148 | ] 149 | type = type || ""; 150 | var ts = type.split("|"); 151 | var errs = []; 152 | if (!type || ~ts.indexOf('push')) { 153 | noFuns.forEach(function (v, i) { 154 | try { 155 | queue.push(v); 156 | } catch (e) { 157 | errs.push(e) 158 | } 159 | }) 160 | } 161 | if (!type || ~ts.indexOf('unshift')) { 162 | noFuns.forEach(function (v, i) { 163 | try { 164 | queue.unshift(v); 165 | } catch (e) { 166 | errs.push(e) 167 | } 168 | }) 169 | } 170 | if (!type || ~ts.indexOf('go')) { 171 | noFuns.forEach(function (v, i) { 172 | try { 173 | queue.go(v); 174 | } catch (e) { 175 | errs.push(e) 176 | } 177 | }) 178 | } 179 | if (!type || ~ts.indexOf('jump')) { 180 | noFuns.forEach(function (v, i) { 181 | try { 182 | queue.jump(v); 183 | } catch (e) { 184 | errs.push(e) 185 | } 186 | }) 187 | } 188 | if (!type || ~ts.indexOf('add')) { 189 | noFuns.forEach(function (v, i) { 190 | try { 191 | queue.add(v); 192 | } catch (e) { 193 | errs.push(e) 194 | } 195 | }) 196 | } 197 | return errs; 198 | } 199 | 200 | function testDescriby(event_name) { 201 | var td = { 202 | "false": { 203 | value: false, 204 | succ_value: false 205 | }, 206 | "true": { 207 | value: true, 208 | succ_value: true 209 | }, 210 | "1": { 211 | value: 1, 212 | succ_value: true 213 | }, 214 | "0": { 215 | value: 0, 216 | succ_value: false 217 | }, 218 | "null": { 219 | value: null, 220 | succ_value: false 221 | }, 222 | "undefined": { 223 | value: undefined, 224 | succ_value: false 225 | }, 226 | "function > false": { 227 | value: function () { 228 | return false; 229 | }, 230 | succ_value: false 231 | }, 232 | "function > true": { 233 | value: function () { 234 | return true; 235 | }, 236 | succ_value: true 237 | }, 238 | "function > undefined": { 239 | value: function () {}, 240 | succ_value: true 241 | }, 242 | "function > throw": { 243 | value: function () { 244 | throw "err"; 245 | }, 246 | succ_value: true 247 | } 248 | } 249 | for (var test in td) { 250 | + function () { 251 | var ts = test 252 | var t = td[ts]; 253 | it("进行" + event_name + "值为: " + ts + " 的测试", function (done) { 254 | testEvent(event_name, t.value, t.succ_value, done); 255 | }) 256 | }() 257 | //break; 258 | } 259 | } 260 | 261 | function testEvent(event_name, event, succ_value, done) { 262 | var testData = { 263 | "workResolve": [], 264 | "workReject": [], 265 | "workFinally": [] 266 | }; 267 | var arr = testData[event_name]; 268 | var dfon = { 269 | "workResolve": 'y', 270 | "workReject": 'n', 271 | "workFinally": 'f' 272 | } 273 | var push = function (vname, i) { 274 | return function (k) { 275 | testData[vname] && testData[vname].push(i); 276 | } 277 | } 278 | var q1 = new Queue(1, { 279 | "workResolve": push("workResolve", 'y'), 280 | "workReject": push("workReject", 'n'), 281 | "workFinally": push("workFinally", 'f'), 282 | "queueEnd": function (vv, Qobj) { 283 | // console.log(event_name,event,succ_value) 284 | // console.log(arr) 285 | // console.log(v) 286 | if (succ_value) { 287 | if (arr.join("") != v) return done("逻辑错误!" + arr) 288 | } else { 289 | if (arr.join("") != "") return done("逻辑错误!" + arr) 290 | } 291 | done(); 292 | } 293 | }); 294 | q1.onError = function () {}; 295 | var con = {}, 296 | v; 297 | con[event_name] = event; 298 | v = dfon[event_name]; 299 | if (event_name == 'workFinally') { 300 | v += v; 301 | } 302 | q1.push(fun2, [9], con); //yf 303 | q1.push(fun2, [9, 9], con).then(null, NULLFUN); //nf 304 | q1.start(); 305 | } 306 | 307 | //普通测试 308 | describe('测试Queue', function () { 309 | describe('队列 插入,执行', function () { 310 | describe('#单个添加测试', function () { 311 | var q1 = new Queue(1) 312 | it('插入非函数报错', function (done) { 313 | var errs = addnoFun(q1); 314 | if (errs.length != 50) { 315 | return done("错误数目不对"); 316 | } 317 | for (var i = 0; i < errs.length; i++) { 318 | var e = errs[i]; 319 | if (!(e instanceof TypeError && e.message.indexOf("Queues only support function") == 0)) { 320 | return done("错误信息不对") 321 | } 322 | } 323 | done(); 324 | }) 325 | it('.push(fun,args,con) OK', function (done) { 326 | q1.push(fun2, [1], { 327 | workResolve: succ(1, done) 328 | }) 329 | q1.start(); 330 | }) 331 | it('.push(fun,args,con) err', function (done) { 332 | q1.push(fun2, [1, 2], { 333 | workReject: succ(2, done) 334 | }).then(null, NULLFUN) 335 | q1.start(); 336 | }) 337 | it('.push(fun,args)', function (done) { 338 | q1.push(fun2, [1]).then(succ(1, done), err(done)); 339 | q1.start(); 340 | }) 341 | it('.push(fun)', function (done) { 342 | q1.push(function () { 343 | return fun2(1) 344 | }).then(succ(1, done), err(done)); 345 | q1.start(); 346 | }) 347 | it('.push 添加 promise function', function (done) { 348 | q1.push(fun2, [1, 2]).then(err(done), function (err) { 349 | if (err !== 2) done("返回参数错误"); 350 | }) 351 | q1.push(fun2, [1]).then(succ(1, done), err(done)); 352 | q1.start(); 353 | }) 354 | it('.push 添加 not promise function', function (done) { 355 | q1.push(function () { 356 | throw 2; 357 | }).then(err(done), function (err) { 358 | if (err !== 2) done("返回参数错误"); 359 | }) 360 | q1.push(function () { 361 | return 1; 362 | }).then(succ(1, done), err(done)); 363 | q1.start(); 364 | }) 365 | it('.unshift 添加 promise function', function (done) { 366 | q1.unshift(fun2, [1]).then(succ(1, done), err(done)); 367 | q1.unshift(fun2, [1, 2]).then(err(done), function (err) { 368 | if (err !== 2) done("返回参数错误"); 369 | }) 370 | q1.start(); 371 | }) 372 | it('.unshift 添加 not promise function', function (done) { 373 | q1.unshift(function () { 374 | return 1; 375 | }).then(succ(1, done), err(done)); 376 | q1.unshift(function () { 377 | throw 2; 378 | }).then(err(done), function (err) { 379 | if (err !== 2) done("返回参数错误"); 380 | }) 381 | q1.start(); 382 | }) 383 | it('.go 添加 promise function', function (done) { 384 | q1.go(fun2, [1, 2]).then(err(done), function (err) { 385 | if (err !== 2) done("返回参数错误"); 386 | }) 387 | q1.go(fun2, [1]).then(succ(1, done), err(done)); 388 | }) 389 | it('.go 添加 not promise function', function (done) { 390 | q1.go(function () { 391 | throw 2; 392 | }).then(err(done), function (err) { 393 | if (err !== 2) done("返回参数错误"); 394 | }) 395 | q1.go(function () { 396 | return 1; 397 | }).then(succ(1, done), err(done)); 398 | }) 399 | it('.jump 添加 promise function', function (done) { 400 | q1.jump(function () { 401 | throw 2; 402 | }).then(err(done), function (err) { 403 | if (err !== 2) done("返回参数错误"); 404 | }) 405 | q1.jump(fun2, [1]).then(succ(1, done), err(done)); 406 | }) 407 | it('.jump 添加 not promise function', function (done) { 408 | q1.jump(function () { 409 | throw 2; 410 | }).then(err(done), function (err) { 411 | if (err !== 2) done("返回参数错误"); 412 | }) 413 | q1.jump(function () { 414 | return 1; 415 | }).then(succ(1, done), err(done)); 416 | }) 417 | it('.add resolve value', function (done) { 418 | q1.add(function (resolve, reject) { 419 | resolve(1) 420 | }, true).then(succ(1, done), err(done)); 421 | }) 422 | it('.add resolve value 异步', function (done) { 423 | q1.add(function (resolve, reject) { 424 | setTimeout(function () { 425 | resolve(1) 426 | }, 0) 427 | }, true).then(succ(1, done), err(done)); 428 | }) 429 | it('.add resolve promise succ', function (done) { 430 | q1.add(function (resolve, reject) { 431 | resolve(fun2(1)) 432 | }, true).then(succ(1, done), err(done)); 433 | }) 434 | it('.add resolve promise err', function (done) { 435 | q1.add(function (resolve, reject) { 436 | resolve(fun2(1, 2)) 437 | }, true).then(err(done), succ(2, done)); 438 | }) 439 | it('.add throw', function (done) { 440 | q1.add(function (resolve, reject) { 441 | throw 2; 442 | }, true).then(err(done), succ(2, done)) 443 | }) 444 | it('.add reject', function (done) { 445 | q1.add(function (resolve, reject) { 446 | reject(2); 447 | }, true).then(err(done), succ(2, done)) 448 | }) 449 | it('.add reject 异步', function (done) { 450 | q1.add(function (resolve, reject) { 451 | setTimeout(function () { 452 | reject(2); 453 | }, 0) 454 | }, true).then(err(done), succ(2, done)) 455 | }) 456 | }) 457 | 458 | describe('#多个添加测试及执行', function () { 459 | var q1 = new Queue(1) 460 | var q2 = new Queue(3) 461 | it('.push 多个', function (done) { 462 | var k = [], 463 | k1 = []; 464 | q1.option("queueEnd", endfun) 465 | q2.option("queueEnd", endfun) 466 | for (var i = 0; i < 5; i++) { 467 | var _err = i === 2 ? 2 : null; 468 | q1.push(fun2, [i, _err]).then(function (data) { 469 | k.push(data) 470 | }, NULLFUN) 471 | q2.push(fun2, [i, _err]).then(function (data) { 472 | k1.push(data) 473 | }, NULLFUN) 474 | } 475 | q1.start(); 476 | q2.start(); 477 | 478 | function endfun() { 479 | if (q1.isStart() || q2.isStart()) return; 480 | if (k.join('') !== '0134') return done("执行顺序错误" + k.join('')); 481 | if (k1.join('') !== '0134') return done("多并发执行顺序错误" + k1.join('')); 482 | done(); 483 | } 484 | }) 485 | it('.unshift 多个', function (done) { 486 | var k = [], 487 | k1 = []; 488 | q1.option("queueEnd", endfun) 489 | q2.option("queueEnd", endfun) 490 | for (var i = 0; i < 5; i++) { 491 | var _err = i === 2 ? 2 : null; 492 | q1.unshift(fun2, [i, _err]).then(function (data) { 493 | k.push(data) 494 | }, NULLFUN) 495 | q2.unshift(fun2, [i, _err]).then(function (data) { 496 | k1.push(data) 497 | }, NULLFUN) 498 | } 499 | q1.start(); 500 | q2.start(); 501 | 502 | function endfun() { 503 | if (q1.isStart() || q2.isStart()) return; 504 | if (k.join('') !== '4310') return done("执行顺序错误"); 505 | if (k1.join('') !== '4310') return done("多并发执行顺序错误"); 506 | done(); 507 | } 508 | }) 509 | it('.go 多个', function (done) { 510 | var k = [], 511 | k1 = []; 512 | q1.option("queueEnd", endfun) 513 | q2.option("queueEnd", endfun) 514 | for (var i = 0; i < 5; i++) { 515 | var _err = i === 2 ? 2 : null; 516 | q1.go(fun2, [i, _err]).then(function (data) { 517 | k.push(data) 518 | }, NULLFUN) 519 | q2.go(fun2, [i, _err]).then(function (data) { 520 | k1.push(data) 521 | }, NULLFUN) 522 | } 523 | 524 | function endfun() { 525 | if (q1.isStart() || q2.isStart()) return; 526 | if (k.join('') !== '0134') return done("执行顺序错误"); 527 | if (k1.join('') !== '0134') return done("多并发执行顺序错误"); 528 | done(); 529 | } 530 | }) 531 | it('.jump 多个', function (done) { 532 | var k = [], 533 | k1 = []; 534 | q1.option("queueEnd", endfun) 535 | q2.option("queueEnd", endfun) 536 | for (var i = 0; i < 5; i++) { 537 | var _err = i === 2 ? 2 : null; 538 | q1.jump(fun2, [i, _err]).then(function (data) { 539 | k.push(data) 540 | }, NULLFUN) 541 | q2.jump(fun2, [i, _err]).then(function (data) { 542 | k1.push(data) 543 | }, NULLFUN) 544 | } 545 | 546 | function endfun() { 547 | if (q1.isStart() || q2.isStart()) return; 548 | if (k.join('') !== '0431') return done("执行顺序错误"); 549 | if (k1.join('') !== '0143') return done("多并发执行顺序错误" + k1.join("")); 550 | done(); 551 | } 552 | }) 553 | it('.add 多个', function (done) { 554 | var k = [], 555 | k1 = []; 556 | q1.option("queueEnd", endfun) 557 | q2.option("queueEnd", endfun) 558 | for (var i = 0; i < 5; i++) { 559 | var _err = i === 2 ? 2 : null; 560 | q1.add(fun2_p(i, _err)).then(function (data) { 561 | k.push(data) 562 | }, NULLFUN) 563 | q2.add(fun2_p(i, _err),{ 564 | 565 | }, false, true).then(function (data) { 566 | k1.push(data) 567 | }, NULLFUN) 568 | } 569 | q1.start(); 570 | q2.start(); 571 | 572 | function endfun() { 573 | if (q1.isStart() || q2.isStart()) return; 574 | if (k.join('') !== '0134') return done("执行顺序错误" + k.join('')); 575 | if (k1.join('') !== '4310') return done("多并发执行顺序错误" + k1.join('')); 576 | done(); 577 | } 578 | }) 579 | }) 580 | 581 | describe('#批量添加测试', function () { 582 | var q1 = new Queue(1) 583 | var q2 = new Queue(3) 584 | it('.addArray([[fun,arg,con]],start,jump) all ok', function (done) { 585 | var k = [], 586 | k1 = [], 587 | jump; 588 | var arr = [ 589 | [fun2, [0]], 590 | [fun2, [1]], 591 | [fun2, [2]] 592 | ] 593 | q1.addArray(arr, 1).then(function (data) { 594 | if (data.join('') !== '012') return done("返回错误"); 595 | done(); 596 | }, err(done)) 597 | q1.jump(fun2, [1]).then(function () { 598 | jump = 1; 599 | }) 600 | q1.addArray(arr, 1, 1).then(function (data) { 601 | if (jump) return done("优先执行出错"); 602 | if (data.join('') !== '012') return done("返回错误"); 603 | }, err(done)) 604 | }) 605 | it('.addArray([[fun,arg,con]],start,jump) 2 > err', function (done) { 606 | var k = [], 607 | k1 = []; 608 | var arr = [ 609 | [fun2, [0]], 610 | [fun2, [1]], 611 | [fun2, [2, 2]] 612 | ] 613 | q2.addArray(arr, 1, 1).then(err(done), succ(2, done)) 614 | }) 615 | it('.addProps(map,start,jump) all ok', function (done) { 616 | var k = [], 617 | k1 = [], 618 | jump; 619 | var map = { 620 | a: [fun2, [1]], 621 | b: [fun2, [2]], 622 | c: [fun2, [3]] 623 | } 624 | q1.addProps(map, 1).then(function (data) { 625 | if (data.a !== 1 || data.b !== 2 || data.c !== 3) return done("返回错误"); 626 | done(); 627 | }, err(done)) 628 | q1.jump(fun2, [1]).then(function () { 629 | jump = 1; 630 | }) 631 | q1.addProps(map, 1, 1).then(function (data) { 632 | if (jump) return done("优先执行出错"); 633 | if (data.a !== 1 || data.b !== 2 || data.c !== 3) return done("返回错误"); 634 | }, err(done)) 635 | }) 636 | it('.addProps(map,start,jump) all err', function (done) { 637 | var k = [], 638 | k1 = [], 639 | jump; 640 | var map = { 641 | a: [fun2, [1]], 642 | b: [fun2, [2, 2]], 643 | c: [fun2, [3]] 644 | } 645 | q2.addProps(map, 1, 1).then(err(done), succ(2, done)) 646 | }) 647 | it('.addLikeArray([arg1,arg2],fun,con,start,jump) all ok', function (done) { 648 | var k = [], 649 | k1 = [], 650 | jump; 651 | var arr = [0, 1, [2]] 652 | q1.addLikeArray(arr, fun3, 1).then(function (data) { 653 | if (data.join('') !== '012') return done("返回错误"); 654 | done(); 655 | }, err(done)) 656 | q1.jump(fun2, [1]).then(function () { 657 | jump = 1; 658 | }) 659 | q1.addLikeArray(arr, fun3, 1, 1).then(function (data) { 660 | if (jump) return done("优先执行出错"); 661 | if (data.join('') !== '012') return done("返回错误"); 662 | }, err(done)) 663 | }) 664 | it('.addLikeArray([arg1,arg2],fun,con,start,jump) 2 > err', function (done) { 665 | var k = [], 666 | k1 = []; 667 | var arr = [0, 1, [2, 2], 3, 4] 668 | q2.addLikeArray(arr, fun3, {}, 1).then(err(done), succ(2, done)) 669 | }) 670 | it('.addLikeArrayEach([arg1,arg2],fun,con,start,jump) all ok', function (done) { 671 | var k = [], 672 | k1 = [], 673 | jump; 674 | var arr = [0, 1, [2]] 675 | q1.addLikeArrayEach(arr, fun4, {}, 1).then(function (data) { 676 | if (data.join('') !== '012') return done("返回错误"); 677 | done(); 678 | }, err(done)); 679 | q1.jump(fun2, [1]).then(function () { 680 | jump = 1; 681 | }) 682 | q1.addLikeArrayEach(arr, fun4, 1, 1).then(function (data) { 683 | if (jump) return done("优先执行出错"); 684 | if (data.join('') !== '012') return done("返回错误"); 685 | }, err(done)) 686 | }) 687 | it('.addLikeArrayEach([arg1,arg2],fun,con,start,jump) 2 > err', function (done) { 688 | var k = [], 689 | k1 = []; 690 | var arr = [0, 1, [2, 2], 3, 4] 691 | q2.addLikeArrayEach(arr, fun4, 1).then(err(done), succ(2, done)) 692 | }) 693 | it('.addLikeProps(map,fun,con,start,jump) all > ok', function (done) { 694 | var k = [], 695 | k1 = [], 696 | jump; 697 | var map = { 698 | a: 1, 699 | b: 2, 700 | c: 3 701 | } 702 | q1.addLikeProps(map, fun3, 1).then(function (data) { 703 | if (data.a !== 1 || data.b !== 2 || data.c !== 3) return done("返回错误"); 704 | done(); 705 | }, err(done)) 706 | q1.jump(fun2, [1]).then(function () { 707 | jump = 1; 708 | }) 709 | q1.addLikeProps(map, fun3, 1, 1).then(function (data) { 710 | if (jump) return done("优先执行出错"); 711 | if (data.a !== 1 || data.b !== 2 || data.c !== 3) return done("返回错误"); 712 | }, err(done)) 713 | }) 714 | it('.addLikeProps(map,fun,con,start,jump) all > b > err', function (done) { 715 | var k = [], 716 | k1 = []; 717 | var map = { 718 | a: 1, 719 | b: [2, 2], 720 | c: 3 721 | } 722 | q2.addLikeProps(map, fun3, {}, 1).then(err(done), succ(2, done)) 723 | }) 724 | it('.addLikePropsEach([arg1,arg2],fun,con,start,jump) all ok', function (done) { 725 | var k = [], 726 | k1 = [], 727 | jump; 728 | var map = { 729 | a: 1, 730 | b: 2, 731 | c: 3 732 | } 733 | q1.addLikePropsEach(map, fun4, 1).then(function (data) { 734 | if (data.a !== 1 || data.b !== 2 || data.c !== 3) return done("返回错误"); 735 | done(); 736 | }, err(done)) 737 | q1.jump(fun2, [1]).then(function () { 738 | jump = 1; 739 | }) 740 | q1.addLikePropsEach(map, fun4, 1, 1).then(function (data) { 741 | if (jump) return done("优先执行出错"); 742 | if (data.a !== 1 || data.b !== 2 || data.c !== 3) return done("返回错误"); 743 | }, err(done)) 744 | }) 745 | it('.addLikePropsEach([arg1,arg2],fun,con,start,jump) 2 > err', function (done) { 746 | var k = [], 747 | k1 = []; 748 | var map = [0, 1, [2, 2], 3, 4] 749 | q2.addLikePropsEach(map, fun4, 1).then(err(done), succ(2, done)) 750 | }) 751 | }) 752 | }) 753 | describe('队列方法测试', function () { 754 | describe('#队列属性', function () { 755 | var q1 = new Queue(1); 756 | var fn = function (v) { 757 | return Q.delay(100, v) 758 | } 759 | it('.getMax()', function (done) { 760 | assert.equal(1, q1.getMax(), "初始错误") 761 | q1.setMax(5); 762 | assert.equal(5, q1.getMax(), "重新设置错误") 763 | q1.setMax(1); 764 | done(); 765 | }); 766 | it('.getLength()', function (done) { 767 | assert.equal(0, q1.getLength(), "初始错误") 768 | q1.push(fn, [1]).then(null, NULLFUN); 769 | assert.equal(1, q1.getLength(), "实时值错误") 770 | q1.addLikeArray([1, 2, 3], fn).then(null, NULLFUN); 771 | assert.equal(4, q1.getLength(), "实时值错误") 772 | q1.clear("clear"); 773 | done(); 774 | }); 775 | it('.getRunCount()', function (done) { 776 | assert.equal(0, q1.getRunCount(), "初始错误") 777 | var p1 = q1.go(fn, [1]).then(null, NULLFUN); 778 | var p2 = q1.go(fn, [2]).then(null, NULLFUN); 779 | var p3 = q1.go(fn, [3]).then(null, NULLFUN); 780 | assert.equal(1, q1.getRunCount(), "实时值错误") 781 | q1.setMax(3); 782 | assert.equal(3, q1.getRunCount(), "实时值错误") 783 | Q.all([p1, p2, p3]).then(function () { 784 | done(); 785 | }) 786 | }); 787 | it('.isStart()', function (done) { 788 | var q2 = new Queue(1); 789 | assert.equal(false, q2.isStart(), "初始错误") 790 | q2.go(fn, [1]).then(null, NULLFUN).then(function (v) { 791 | done(assert.equal(false, q2.isStart(), "实时值错误")); 792 | }); 793 | assert.equal(true, q2.isStart(), "实时值错误") 794 | }); 795 | }) 796 | 797 | describe('#队列控制测试', function () { 798 | var q1 = new Queue(1) 799 | it('.start()', function (done) { 800 | var p = q1.push(fun2, [1]); 801 | q1.start(); 802 | setTimeout(function () { 803 | p.then(succ(1, done)) 804 | }, MAXTIME * 1.1) 805 | }) 806 | it('.stop()', function (done) { 807 | var k = []; 808 | for (var i = 0; i < 5; i++) { 809 | q1.push(fun2, [i]).then(function (data) { 810 | k.push(data) 811 | }) 812 | } 813 | q1.start(); 814 | q1.stop(); 815 | setTimeout(function () { 816 | //console.log(k) 817 | if (k.join('') !== "0") return done("暂停失败!") 818 | q1.start(); 819 | q1.option("queueEnd", function () { 820 | if (k.join('') !== "01234") return done("恢复执行出现问题!") 821 | done(); 822 | }) 823 | }, MAXTIME * 2.1) 824 | }) 825 | it('.clear()', function (done) { 826 | var k = [], 827 | ke = []; 828 | q1.option("queueEnd", null); 829 | for (var i = 0; i < 5; i++) { 830 | q1.push(fun2, [i]).then(function (data) { 831 | k.push(data) 832 | }, function (err) { 833 | ke.push(err) 834 | }) 835 | } 836 | q1.start() 837 | q1.clear(2); 838 | setTimeout(function () { 839 | if (k.join('') !== "0" || ke.join('') !== "2222") return done("清除执行时出现问题!") 840 | done(); 841 | }, MAXTIME * 2.1); 842 | }) 843 | it('.setMax()', function (done) { 844 | var k = [], 845 | ke = []; 846 | var mn = 50 847 | for (var i = 0; i < mn; i++) { 848 | q1.push(fun2, [i]).then(function (data) { 849 | k.push(data) 850 | }, function (err) { 851 | ke.push(err) 852 | }) 853 | }; 854 | q1.start(); 855 | q1.setMax(mn); 856 | setTimeout(function () { 857 | if (k.length < mn) return done("设置setMax出现问题!") 858 | done(); 859 | }, MAXTIME * 1.5) 860 | }) 861 | it('.setMax(-1) ', function (done) { 862 | try{ 863 | q1.setMax(-1); 864 | }catch(err){ 865 | if (err.message == 'The "max" value is invalid') { 866 | done(); 867 | } 868 | } 869 | }) 870 | }) 871 | describe('#队列事件测试', function () { 872 | // var q1 = new Queue(1,{ 873 | // "workResolve":function(){console.log(this,arguments)} //成功 874 | // ,"workReject":function(){} //失败 875 | // ,"queueStart":function(){} //队列开始 876 | // ,"queueEnd":function(){} //队列完成 877 | // ,"event_add":function(){} //有执行项添加进执行单元后执行 878 | // }) 879 | it('#事件顺序测试', function (done) { 880 | var add1 = 0; 881 | var finally1 = 0; 882 | var arr = []; 883 | var push = function (i) { 884 | return function () { 885 | arr.push(i); 886 | } 887 | } 888 | var q1 = new Queue(1, { 889 | "workAdd": function () { 890 | add1++; 891 | }, 892 | "queueStart": push("b"), 893 | "queueEnd": function (v, Qobj) { 894 | push("e")(); 895 | //console.log(arr.join("")); 896 | if (arr.join("") != "b1yf2nfy3fn4fyfnfe") return done("顺序错误!") 897 | done(); 898 | }, 899 | "workResolve": push("y"), 900 | "workReject": push("n"), 901 | "workFinally": push("f") 902 | }); 903 | 904 | q1.push(function () { 905 | return 1 906 | }, [1], { 907 | workResolve: function () { 908 | push(1)() 909 | } 910 | }); 911 | q1.push(function () { 912 | throw 1 913 | }, { 914 | workReject: function () { 915 | push(2)() 916 | } 917 | }).then(null, NULLFUN); 918 | q1.push(function () { 919 | return 1 920 | }, { 921 | workFinally: function () { 922 | push(3)() 923 | } 924 | }); 925 | q1.push(function () { 926 | throw 1 927 | }, { 928 | workFinally: function () { 929 | push(4)() 930 | } 931 | }).then(null, NULLFUN); 932 | 933 | q1.push(fun2, [9]); 934 | q1.push(fun2, [9, 9]).then(null, NULLFUN); 935 | 936 | q1.start(); 937 | }) 938 | describe('#onError 事件', function () { 939 | it('#默认打印错误', function (done) { 940 | var olderr = console.error; 941 | var errmark = 'errmark'; 942 | console.error = function(err){ 943 | console.error = olderr; 944 | if(err === errmark){ 945 | done(); 946 | }else{ 947 | done('测试失败!') 948 | } 949 | } 950 | var q1 = new Queue(1, { 951 | workAdd: function(){ 952 | throw errmark; 953 | } 954 | }); 955 | q1.push(function () {}); 956 | }) 957 | 958 | it('#自定义onError 不为Function', function (done) { 959 | var throwfun = function (err) { 960 | return function () { 961 | throw err; 962 | } 963 | } 964 | var q1 = new Queue(1, { 965 | workAdd: throwfun("workAdd") 966 | }); 967 | q1.onError = {}; 968 | q1.push(function () {}); 969 | done(); 970 | }) 971 | 972 | it('#队列事件出错捕获 , 自定义onError', function (done) { 973 | var errnb = {}; 974 | var throwfun = function (err) { 975 | return function () { 976 | throw err; 977 | } 978 | } 979 | var q1 = new Queue(1, { 980 | queueStart: throwfun("queueStart"), 981 | queueEnd: throwfun("queueEnd"), 982 | workResolve: throwfun("workResolve"), 983 | workReject: throwfun("workReject") 984 | }); 985 | q1.onError = function (err) { 986 | if (errnb[err]) { 987 | errnb[err] += 1 988 | } else { 989 | errnb[err] = 1; 990 | } 991 | if (err == "queueEnd") { 992 | if (errnb["queueStart"] == 1 && 993 | errnb["queueEnd"] == 1 && 994 | errnb["workReject"] == 2 && 995 | errnb["workResolve"] == 2) { 996 | done() 997 | } else { 998 | done("onError 运行错误") 999 | } 1000 | } 1001 | } 1002 | q1.push(function () { 1003 | return 1 1004 | }); 1005 | ADD(q1, "push") 1006 | q1.push(function () { 1007 | throw 1 1008 | }).then(null, NULLFUN) 1009 | q1.start(); 1010 | }) 1011 | }) 1012 | 1013 | describe('#队列事件逻辑测试', function () { 1014 | testDescriby("workResolve"); 1015 | testDescriby("workReject"); 1016 | testDescriby("workFinally"); 1017 | }) 1018 | 1019 | 1020 | }) 1021 | describe('#重试,超时,自动运行', function () { 1022 | describe('#重试', function () { 1023 | // it('#retry new(2,{retry:5})',function(){ 1024 | 1025 | // }) 1026 | it('#队列重试 默认', function (done) { 1027 | var q1 = new Queue(2, { 1028 | "retry": 0, 1029 | "retryIsJump": 0 //重试模式 0:搁置执行(插入队列尾部重试),1:优先执行 (插入队列头部重试) 1030 | , 1031 | '_test': 0 1032 | }); 1033 | if (q1.option("retry") == 0) q1.option("retry", 5); 1034 | var rnumb = 0, 1035 | rnumb1 = 0; 1036 | q1.option("queueEnd", function () { 1037 | if (rnumb == 0 || rnumb1 == 0) return done("未重试") 1038 | if (rnumb !== 5 || rnumb1 !== 5) return done("重试次数错误!") 1039 | done(); 1040 | }) 1041 | q1.go(function () { 1042 | rnumb++; 1043 | if (rnumb < 5) throw "err" 1044 | return 1; 1045 | }) 1046 | q1.go(function () { 1047 | rnumb1++; 1048 | if (rnumb1 < 5) throw "err" 1049 | return 1; 1050 | }) 1051 | }) 1052 | it('#队列重试 重试优先', function (done) { 1053 | var q1 = new Queue(1, { 1054 | "retry": 5, 1055 | "retryIsJump": 1 //重试模式 0:搁置执行(插入队列尾部重试),1:优先执行 (插入队列头部重试) 1056 | }) 1057 | var rnumb = 0; 1058 | q1.go(function () { 1059 | var def = Q.defer() 1060 | setTimeout(function () { 1061 | rnumb++; 1062 | if (rnumb < 6) def.reject("err"); 1063 | else def.resolve(1); 1064 | }, 20) 1065 | return def.promise; 1066 | }) 1067 | q1.go(function () { 1068 | return rnumb 1069 | }).then(succ(6, done), err(done)) 1070 | }) 1071 | it('#执行单元重试 优先队列设置', function (done) { 1072 | var q1 = new Queue(1, { 1073 | "retry": 5, 1074 | "retryIsJump": 1 //重试模式 1075 | }) 1076 | var qobj = { 1077 | "retry": 3, 1078 | "retryIsJump": 1 //重试模式 1079 | , 1080 | "_test": 1 1081 | } 1082 | var rnumb = 0, 1083 | rnumb1 = 0; 1084 | q1.go(function () { 1085 | var def = Q.defer() 1086 | setTimeout(function () { 1087 | rnumb++; 1088 | if (rnumb < 5) def.reject(rnumb); 1089 | else def.resolve(1); 1090 | }, 20) 1091 | return def.promise; 1092 | }, qobj).then(function () { 1093 | done("重试出问题2"); 1094 | }, function (err) { 1095 | if (err != 4) done("重试出问题1") 1096 | }) 1097 | q1.go(function () { 1098 | return rnumb 1099 | }, qobj).then(succ(4, done), err(done)) 1100 | }) 1101 | it('重试延迟 sleep') 1102 | }) 1103 | describe('#超时', function () { 1104 | it('#超时 默认', function (done) { 1105 | var q1 = new Queue(2, { 1106 | "timeout": 100 1107 | }) 1108 | q1.go(function () { 1109 | var def = Q.defer(); 1110 | setTimeout(function () { 1111 | def.resolve("OK") 1112 | }, 200) 1113 | return def.promise; 1114 | }).then(err(done), succ("timeout", done)) 1115 | //}).then(function(d){console.log("d:",d)},function(e){console.log("e:",e)}) 1116 | }) 1117 | it('#超时 单独自定义', function (done) { 1118 | var q1 = new Queue(2, { 1119 | "timeout": 100 1120 | }) 1121 | q1.go(function () { 1122 | var def = Q.defer(); 1123 | setTimeout(function () { 1124 | def.resolve("OK") 1125 | }, 200) 1126 | return def.promise; 1127 | }, { 1128 | timeout: 300 1129 | }).then(succ("OK", done), err(done)) 1130 | }) 1131 | }) 1132 | describe('#自动运行 autoRun',function(){ 1133 | it('#autoRun 默认false', function(done){ 1134 | var queue = new Queue(1, {queueStart:function(){ 1135 | done('逻辑错误'); 1136 | }}); 1137 | ADD(queue,'nostart') 1138 | setTimeout(function(){ 1139 | done(); 1140 | },100) 1141 | }) 1142 | it('#autoRun true',function(done){ 1143 | var queue = new Queue(1,{ autoRun: true}) 1144 | queue.push(fun2,[1]).then(succ(1,done)); 1145 | }) 1146 | }) 1147 | }) 1148 | describe("#使用其他Promise实现", function () { 1149 | var promises = { 1150 | "easy-promise": require('easy-promise'), 1151 | "q": require('q') 1152 | } 1153 | if (typeof Promise == "function" && Promise.prototype.then) { 1154 | promises["原生Promise"] = Promise; 1155 | } 1156 | for (var _p in promises) { 1157 | (function (name, Promise) { 1158 | var _then; 1159 | if (Promise.prototype && Promise.prototype.then) { 1160 | _then = Promise.prototype.then; 1161 | } else if (Promise.defer) { 1162 | _then = Promise.defer().promise.then; 1163 | } 1164 | 1165 | it(name, function (done) { 1166 | var _Queue = Queue.createUse(Promise); 1167 | var queue = new _Queue(1); 1168 | var mark; 1169 | var promise = queue.go(fun2, [1]).then(function (d) { 1170 | mark = d; 1171 | }).then(function () { 1172 | if (mark != 1) { 1173 | return done("队列运行不正常") 1174 | }; 1175 | //if(promise.return){reutrn done("未成功切换Promise实现")} 1176 | if (_then === promise.then) done(); 1177 | }) 1178 | 1179 | }) 1180 | })(_p, promises[_p]) 1181 | } 1182 | 1183 | }) 1184 | }) 1185 | }); --------------------------------------------------------------------------------