├── .eslintrc.js ├── .travis.yml ├── README.md ├── _config.yml ├── dist ├── vue-methods-promise.js ├── vue-methods-promise.js.map ├── vue-methods-promise.min.js └── vue-methods-promise.min.js.map ├── gulpfile.js ├── package.json ├── src ├── hijack.js ├── index.js ├── isObject.js ├── isPromise.js └── methodsPromise.js └── test ├── browser └── index.test.js └── unit ├── hijack.test.js ├── isObject.test.js ├── isPromise.test.js └── methodsPromise.test.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['standard'] 4 | } 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | - "7" 5 | install: 6 | - npm install 7 | script: 8 | - npm run test -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/lzxb/vue-methods-promise.svg?branch=master)](https://travis-ci.org/lzxb/vue-methods-promise) 2 | [![dependencies Status](https://david-dm.org/lzxb/vue-methods-promise/status.svg)](https://david-dm.org/lzxb/vue-methods-promise) 3 | [![devDependencies Status](https://david-dm.org/lzxb/vue-methods-promise/dev-status.svg)](https://david-dm.org/lzxb/vue-methods-promise?type=dev) 4 | [![Known Vulnerabilities](https://snyk.io/test/npm/vue-methods-promise/badge.svg)](https://snyk.io/test/npm/vue-methods-promise) 5 | [![npm](https://img.shields.io/npm/v/vue-methods-promise.svg?style=flat-square)](https://www.npmjs.com/package/vue-methods-promise) 6 | [![npm](https://img.shields.io/npm/dt/vue-methods-promise.svg?style=flat-square)](https://www.npmjs.com/package/vue-methods-promise) 7 | 8 | # vue-methods-promise 9 | ``` 10 | Let Vue methods support promise 11 | ``` 12 | 13 | ### Usage 14 | ``` 15 | npm install --save vue-methods-promise 16 | ``` 17 | ```javascript 18 | // Installation 19 | import Vue from 'vue' 20 | import vueMethodsPromise from 'vue-methods-promise' 21 | 22 | Vue.use(vueMethodsPromise, { 23 | hookName: '$promise', // Component default hook name 24 | promise: (mp) => { // Promise callback 25 | mp 26 | .then((function (res) { 27 | console.log(res) 28 | }) 29 | .catch(function (err) { 30 | console.log(err.msg) // Test error 31 | }) 32 | } 33 | }) 34 | 35 | // Usage 36 | export default { 37 | mounted () { 38 | this.test() 39 | }, 40 | methods: { // All return Promise type, will be dealt with 41 | test () { 42 | return Promise.reject(new Error({ msg: 'Test error' })) 43 | } 44 | } 45 | } 46 | 47 | ``` -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /dist/vue-methods-promise.js: -------------------------------------------------------------------------------- 1 | (function (global, factory) { 2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 3 | typeof define === 'function' && define.amd ? define(factory) : 4 | (global.vueMethodsPromise = factory()); 5 | }(this, (function () { 'use strict'; 6 | 7 | var isObject = function (obj) { 8 | return Object.prototype.toString.call(obj) === '[object Object]'; 9 | }; 10 | 11 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { 12 | return typeof obj; 13 | } : function (obj) { 14 | return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; 15 | }; 16 | 17 | function isPromise(obj) { 18 | return Object.prototype.toString.call(obj) === '[object Promise]' || !!obj && ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' || typeof obj === 'function') && typeof obj.constructor === 'function' && !Object.hasOwnProperty.call(obj, 'constructor') && obj.constructor.name === 'Promise'; 19 | } 20 | 21 | function hijack(opt, native) { 22 | function vueMethodsPromise() { 23 | var back = native.apply(this, arguments); 24 | if (isPromise(back)) { 25 | if (typeof this[opt.hookName] === 'function') { 26 | var hookBack = this[opt.hookName](back); 27 | if (isPromise(hookBack)) { 28 | opt.promise.call(this, back); 29 | } 30 | } else { 31 | opt.promise.call(this, back); 32 | } 33 | } 34 | return back; 35 | } 36 | vueMethodsPromise._vueMethodsPromise = true; // 加个标记,避免重复劫持,导致栈溢出 37 | return vueMethodsPromise; 38 | } 39 | 40 | var methodsPromise = (function () { 41 | var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 42 | 43 | // Configure the hook function 44 | if (typeof opt.hookName !== 'string') { 45 | opt.hookName = '$promise'; 46 | } 47 | // Global hook function 48 | if (typeof opt.promise !== 'function') { 49 | opt.promise = function (mp) { 50 | mp.catch(function (err) { 51 | console.log(err); 52 | }); 53 | }; 54 | } 55 | 56 | return { 57 | beforeCreate: function beforeCreate() { 58 | var methods = this.$options.methods; 59 | 60 | if (!isObject(methods)) return; 61 | Object.keys(methods).forEach(function (k) { 62 | var fn = methods[k]; 63 | if (fn._vueMethodsPromise !== true && typeof fn === 'function' && k !== opt.hookName) { 64 | methods[k] = hijack(opt, fn); 65 | } 66 | }); 67 | } 68 | }; 69 | }); 70 | 71 | function install(Vue, opt) { 72 | if (install.installed) return; // already installed 73 | 74 | Vue.mixin(methodsPromise(opt)); 75 | } 76 | 77 | return install; 78 | 79 | }))); 80 | //# sourceMappingURL=vue-methods-promise.js.map 81 | -------------------------------------------------------------------------------- /dist/vue-methods-promise.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"vue-methods-promise.js","sources":["../src/isObject.js","../src/isPromise.js","../src/hijack.js","../src/methodsPromise.js","../src/index.js"],"sourcesContent":["export default function (obj) {\n return Object.prototype.toString.call(obj) === '[object Object]'\n}\n","export default function isPromise (obj) {\n return Object.prototype.toString.call(obj) === '[object Promise]' || (!!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.constructor === 'function' && !Object.hasOwnProperty.call(obj, 'constructor') && obj.constructor.name === 'Promise')\n}\n","import isPromise from './isPromise'\n\nexport default function hijack (opt, native) {\n function vueMethodsPromise () {\n let back = native.apply(this, arguments)\n if (isPromise(back)) {\n if (typeof this[opt.hookName] === 'function') {\n let hookBack = this[opt.hookName](back)\n if (isPromise(hookBack)) {\n opt.promise.call(this, back)\n }\n } else {\n opt.promise.call(this, back)\n }\n }\n return back\n }\n vueMethodsPromise._vueMethodsPromise = true // 加个标记,避免重复劫持,导致栈溢出\n return vueMethodsPromise\n}\n","import isObject from './isObject'\nimport hijack from './hijack'\n\nexport default (opt = {}) => {\n // Configure the hook function\n if (typeof opt.hookName !== 'string') {\n opt.hookName = '$promise'\n }\n // Global hook function\n if (typeof opt.promise !== 'function') {\n opt.promise = (mp) => {\n mp.catch((err) => {\n console.log(err)\n })\n }\n }\n\n return {\n beforeCreate () {\n const { methods } = this.$options\n if (!isObject(methods)) return\n Object.keys(methods).forEach((k) => {\n let fn = methods[k]\n if (fn._vueMethodsPromise !== true && typeof fn === 'function' && k !== opt.hookName) {\n methods[k] = hijack(opt, fn)\n }\n })\n }\n }\n}\n","import methodsPromise from './methodsPromise'\n\nexport default function install (Vue, opt) {\n if (install.installed) return // already installed\n\n Vue.mixin(methodsPromise(opt))\n}\n"],"names":["obj","Object","prototype","toString","call","isPromise","constructor","hasOwnProperty","name","hijack","opt","native","vueMethodsPromise","back","apply","arguments","hookName","hookBack","promise","_vueMethodsPromise","mp","catch","err","log","methods","$options","isObject","keys","forEach","k","fn","install","Vue","installed","mixin","methodsPromise"],"mappings":";;;;;;AAAA,eAAe,UAAUA,GAAV,EAAe;SACrBC,OAAOC,SAAP,CAAiBC,QAAjB,CAA0BC,IAA1B,CAA+BJ,GAA/B,MAAwC,iBAA/C;;;;;;;;;ACDa,SAASK,SAAT,CAAoBL,GAApB,EAAyB;SAC/BC,OAAOC,SAAP,CAAiBC,QAAjB,CAA0BC,IAA1B,CAA+BJ,GAA/B,MAAwC,kBAAxC,IAA+D,CAAC,CAACA,GAAF,KAAU,QAAOA,GAAP,yCAAOA,GAAP,OAAe,QAAf,IAA2B,OAAOA,GAAP,KAAe,UAApD,KAAmE,OAAOA,IAAIM,WAAX,KAA2B,UAA9F,IAA4G,CAACL,OAAOM,cAAP,CAAsBH,IAAtB,CAA2BJ,GAA3B,EAAgC,aAAhC,CAA7G,IAA+JA,IAAIM,WAAJ,CAAgBE,IAAhB,KAAyB,SAA9P;;;ACCa,SAASC,MAAT,CAAiBC,GAAjB,EAAsBC,MAAtB,EAA8B;WAClCC,iBAAT,GAA8B;QACxBC,OAAOF,OAAOG,KAAP,CAAa,IAAb,EAAmBC,SAAnB,CAAX;QACIV,UAAUQ,IAAV,CAAJ,EAAqB;UACf,OAAO,KAAKH,IAAIM,QAAT,CAAP,KAA8B,UAAlC,EAA8C;YACxCC,WAAW,KAAKP,IAAIM,QAAT,EAAmBH,IAAnB,CAAf;YACIR,UAAUY,QAAV,CAAJ,EAAyB;cACnBC,OAAJ,CAAYd,IAAZ,CAAiB,IAAjB,EAAuBS,IAAvB;;OAHJ,MAKO;YACDK,OAAJ,CAAYd,IAAZ,CAAiB,IAAjB,EAAuBS,IAAvB;;;WAGGA,IAAP;;oBAEgBM,kBAAlB,GAAuC,IAAvC,CAf2C;SAgBpCP,iBAAP;;;ACfF,sBAAe,YAAc;MAAbF,GAAa,uEAAP,EAAO;;;MAEvB,OAAOA,IAAIM,QAAX,KAAwB,QAA5B,EAAsC;QAChCA,QAAJ,GAAe,UAAf;;;MAGE,OAAON,IAAIQ,OAAX,KAAuB,UAA3B,EAAuC;QACjCA,OAAJ,GAAc,UAACE,EAAD,EAAQ;SACjBC,KAAH,CAAS,UAACC,GAAD,EAAS;gBACRC,GAAR,CAAYD,GAAZ;OADF;KADF;;;SAOK;gBAAA,0BACW;UACNE,OADM,GACM,KAAKC,QADX,CACND,OADM;;UAEV,CAACE,SAASF,OAAT,CAAL,EAAwB;aACjBG,IAAP,CAAYH,OAAZ,EAAqBI,OAArB,CAA6B,UAACC,CAAD,EAAO;YAC9BC,KAAKN,QAAQK,CAAR,CAAT;YACIC,GAAGX,kBAAH,KAA0B,IAA1B,IAAkC,OAAOW,EAAP,KAAc,UAAhD,IAA8DD,MAAMnB,IAAIM,QAA5E,EAAsF;kBAC5Ea,CAAR,IAAapB,OAAOC,GAAP,EAAYoB,EAAZ,CAAb;;OAHJ;;GAJJ;CAdF;;ACDe,SAASC,OAAT,CAAkBC,GAAlB,EAAuBtB,GAAvB,EAA4B;MACrCqB,QAAQE,SAAZ,EAAuB,OADkB;;MAGrCC,KAAJ,CAAUC,eAAezB,GAAf,CAAV;;;;;"} -------------------------------------------------------------------------------- /dist/vue-methods-promise.min.js: -------------------------------------------------------------------------------- 1 | !function(o,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):o.vueMethodsPromise=t()}(this,function(){"use strict";function o(o){return"[object Promise]"===Object.prototype.toString.call(o)||!!o&&("object"===(void 0===o?"undefined":i(o))||"function"==typeof o)&&"function"==typeof o.constructor&&!Object.hasOwnProperty.call(o,"constructor")&&"Promise"===o.constructor.name}function t(t,e){function n(){var n=e.apply(this,arguments);if(o(n))if("function"==typeof this[t.hookName]){var i=this[t.hookName](n);o(i)&&t.promise.call(this,n)}else t.promise.call(this,n);return n}return n._vueMethodsPromise=!0,n}function e(o,t){e.installed||o.mixin(r(t))}var n=function(o){return"[object Object]"===Object.prototype.toString.call(o)},i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},r=function(){var o=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return"string"!=typeof o.hookName&&(o.hookName="$promise"),"function"!=typeof o.promise&&(o.promise=function(o){o.catch(function(o){console.log(o)})}),{beforeCreate:function(){var e=this.$options.methods;n(e)&&Object.keys(e).forEach(function(n){var i=e[n];i._vueMethodsPromise!==!0&&"function"==typeof i&&n!==o.hookName&&(e[n]=t(o,i))})}}};return e}); 2 | //# sourceMappingURL=vue-methods-promise.min.js.map 3 | -------------------------------------------------------------------------------- /dist/vue-methods-promise.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"vue-methods-promise.min.js","sources":["../src/isPromise.js","../src/hijack.js","../src/index.js","../src/isObject.js","../src/methodsPromise.js"],"sourcesContent":["export default function isPromise (obj) {\n return Object.prototype.toString.call(obj) === '[object Promise]' || (!!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.constructor === 'function' && !Object.hasOwnProperty.call(obj, 'constructor') && obj.constructor.name === 'Promise')\n}\n","import isPromise from './isPromise'\n\nexport default function hijack (opt, native) {\n function vueMethodsPromise () {\n let back = native.apply(this, arguments)\n if (isPromise(back)) {\n if (typeof this[opt.hookName] === 'function') {\n let hookBack = this[opt.hookName](back)\n if (isPromise(hookBack)) {\n opt.promise.call(this, back)\n }\n } else {\n opt.promise.call(this, back)\n }\n }\n return back\n }\n vueMethodsPromise._vueMethodsPromise = true // 加个标记,避免重复劫持,导致栈溢出\n return vueMethodsPromise\n}\n","import methodsPromise from './methodsPromise'\n\nexport default function install (Vue, opt) {\n if (install.installed) return // already installed\n\n Vue.mixin(methodsPromise(opt))\n}\n","export default function (obj) {\n return Object.prototype.toString.call(obj) === '[object Object]'\n}\n","import isObject from './isObject'\nimport hijack from './hijack'\n\nexport default (opt = {}) => {\n // Configure the hook function\n if (typeof opt.hookName !== 'string') {\n opt.hookName = '$promise'\n }\n // Global hook function\n if (typeof opt.promise !== 'function') {\n opt.promise = (mp) => {\n mp.catch((err) => {\n console.log(err)\n })\n }\n }\n\n return {\n beforeCreate () {\n const { methods } = this.$options\n if (!isObject(methods)) return\n Object.keys(methods).forEach((k) => {\n let fn = methods[k]\n if (fn._vueMethodsPromise !== true && typeof fn === 'function' && k !== opt.hookName) {\n methods[k] = hijack(opt, fn)\n }\n })\n }\n }\n}\n"],"names":["isPromise","obj","Object","prototype","toString","call","constructor","hasOwnProperty","name","hijack","opt","native","vueMethodsPromise","back","apply","this","arguments","hookName","hookBack","promise","_vueMethodsPromise","install","Vue","installed","mixin","methodsPromise","mp","catch","err","log","methods","$options","isObject","keys","forEach","k","fn"],"mappings":"4LAAe,SAASA,GAAWC,SACc,qBAAxCC,OAAOC,UAAUC,SAASC,KAAKJ,MAAkCA,IAAuB,qBAARA,gBAAAA,KAAmC,kBAARA,KAAkD,kBAApBA,GAAIK,cAA+BJ,OAAOK,eAAeF,KAAKJ,EAAK,gBAA2C,YAAzBA,EAAIK,YAAYE,KCCxO,QAASC,GAAQC,EAAKC,WAC1BC,QACHC,GAAOF,EAAOG,MAAMC,KAAMC,cAC1BhB,EAAUa,MACsB,kBAAvBE,MAAKL,EAAIO,UAA0B,IACxCC,GAAWH,KAAKL,EAAIO,UAAUJ,EAC9Bb,GAAUkB,MACRC,QAAQd,KAAKU,KAAMF,UAGrBM,QAAQd,KAAKU,KAAMF,SAGpBA,YAESO,oBAAqB,EAChCR,EChBM,QAASS,GAASC,EAAKZ,GAChCW,EAAQE,aAERC,MAAMC,EAAef,ICL3B,MAAe,SAAUT,SACwB,oBAAxCC,OAAOC,UAAUC,SAASC,KAAKJ,gOCExBS,mEAEc,gBAAjBA,GAAIO,aACTA,SAAW,YAGU,kBAAhBP,GAAIS,YACTA,QAAU,SAACO,KACVC,MAAM,SAACC,WACAC,IAAID,mCAONE,GAAYf,KAAKgB,SAAjBD,OACHE,GAASF,WACPG,KAAKH,GAASI,QAAQ,SAACC,MACxBC,GAAKN,EAAQK,EACbC,GAAGhB,sBAAuB,GAAsB,kBAAPgB,IAAqBD,IAAMzB,EAAIO,aAClEkB,GAAK1B,EAAOC,EAAK0B"} -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const eslint = require('gulp-eslint') 3 | const clear = require('clear') 4 | const { rollup } = require('rollup') 5 | const babel = require('rollup-plugin-babel')({ babelrc: false, presets: ['es2015-rollup'] }) 6 | const uglify = require('rollup-plugin-uglify') 7 | const ava = require('gulp-ava') 8 | 9 | const moduleName = 'vueMethodsPromise' 10 | const destName = 'vue-methods-promise' 11 | 12 | // Test code style 13 | gulp.task('lint', () => { 14 | clear() 15 | return gulp.src(['**/*.js', '!node_modules/**', '!dist/**']) 16 | .pipe(eslint()) 17 | .pipe(eslint.format()) 18 | .pipe(eslint.failAfterError()) 19 | }) 20 | 21 | // Compiler development version 22 | gulp.task('build:dev', ['lint'], () => { 23 | return rollup({ 24 | entry: 'src/index.js', 25 | plugins: [babel] 26 | }) 27 | .then((bundle) => { 28 | bundle.write({ 29 | moduleName, 30 | format: 'umd', 31 | dest: `dist/${destName}.js`, 32 | sourceMap: true 33 | }) 34 | }) 35 | }) 36 | 37 | // Compile production 38 | gulp.task('build:prod', ['build:dev'], () => { 39 | return rollup({ 40 | entry: 'src/index.js', 41 | plugins: [babel, uglify()] 42 | }) 43 | .then((bundle) => { 44 | bundle.write({ 45 | moduleName, 46 | format: 'umd', 47 | dest: `dist/${destName}.min.js`, 48 | sourceMap: true 49 | }) 50 | }) 51 | }) 52 | 53 | // Component testing 54 | gulp.task('test', ['build:prod'], () => { 55 | return gulp.src('test/**.test.js') 56 | .pipe(ava({ 57 | verbose: true // Enable verbose output 58 | })) 59 | }) 60 | 61 | gulp.task('default', ['lint', 'build:dev', 'build:prod', 'test']) 62 | 63 | if (process.env.NODE_ENV !== 'production') { 64 | gulp.watch(['**/**/**.js', '!node_modules/**', '!dist/**'], ['default']) 65 | } 66 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-methods-promise", 3 | "version": "0.2.2", 4 | "description": "Let Vue methods support promise", 5 | "main": "dist/vue-methods-promise.js", 6 | "scripts": { 7 | "cross-env": "node_modules/.bin/cross-env", 8 | "gulp": "node_modules/.bin/gulp", 9 | "dev": "npm run gulp", 10 | "dist": "npm run cross-env NODE_ENV=production npm run gulp", 11 | "test": "npm run cross-env NODE_ENV=production npm run gulp" 12 | }, 13 | "files": [ 14 | "dist/", 15 | "src/" 16 | ], 17 | "Keywords": [ 18 | "vue", 19 | "vue2", 20 | "vue-promise", 21 | "vue2-promise", 22 | "vue-methods-promise", 23 | "vuepromise", 24 | "vuePromise" 25 | ], 26 | "repository": { 27 | "type": "git", 28 | "url": "git+https://github.com/lzxb/vue-methods-promise.git" 29 | }, 30 | "author": "", 31 | "license": "ISC", 32 | "bugs": { 33 | "url": "https://github.com/lzxb/vue-methods-promise/issues" 34 | }, 35 | "homepage": "https://github.com/lzxb/vue-methods-promise#readme", 36 | "devDependencies": { 37 | "babel-preset-es2015": "^6.22.0", 38 | "babel-preset-es2015-rollup": "^3.0.0", 39 | "babel-register": "^6.23.0", 40 | "clear": "0.0.1", 41 | "cross-env": "^3.1.4", 42 | "eslint-config-standard": "^8.0.0-beta.0", 43 | "eslint-plugin-import": "^2.2.0", 44 | "eslint-plugin-node": "^4.1.0", 45 | "eslint-plugin-promise": "^3.5.0", 46 | "eslint-plugin-standard": "^2.1.1", 47 | "gulp": "^3.9.1", 48 | "gulp-ava": "^0.16.0", 49 | "gulp-eslint": "^3.0.1", 50 | "jsdom": "^9.11.0", 51 | "rollup": "^0.41.4", 52 | "rollup-plugin-babel": "^2.7.1", 53 | "rollup-plugin-uglify": "^1.0.1" 54 | }, 55 | "babel": { 56 | "presets": [ 57 | "es2015" 58 | ] 59 | }, 60 | "ava": { 61 | "require": [ 62 | "babel-register" 63 | ] 64 | } 65 | } -------------------------------------------------------------------------------- /src/hijack.js: -------------------------------------------------------------------------------- 1 | import isPromise from './isPromise' 2 | 3 | export default function hijack (opt, native) { 4 | function vueMethodsPromise () { 5 | let back = native.apply(this, arguments) 6 | if (isPromise(back)) { 7 | if (typeof this[opt.hookName] === 'function') { 8 | let hookBack = this[opt.hookName](back) 9 | if (isPromise(hookBack)) { 10 | opt.promise.call(this, back) 11 | } 12 | } else { 13 | opt.promise.call(this, back) 14 | } 15 | } 16 | return back 17 | } 18 | vueMethodsPromise._vueMethodsPromise = true // 加个标记,避免重复劫持,导致栈溢出 19 | return vueMethodsPromise 20 | } 21 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import methodsPromise from './methodsPromise' 2 | 3 | export default function install (Vue, opt) { 4 | if (install.installed) return // already installed 5 | 6 | Vue.mixin(methodsPromise(opt)) 7 | } 8 | -------------------------------------------------------------------------------- /src/isObject.js: -------------------------------------------------------------------------------- 1 | export default function (obj) { 2 | return Object.prototype.toString.call(obj) === '[object Object]' 3 | } 4 | -------------------------------------------------------------------------------- /src/isPromise.js: -------------------------------------------------------------------------------- 1 | export default function isPromise (obj) { 2 | return Object.prototype.toString.call(obj) === '[object Promise]' || (!!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.constructor === 'function' && !Object.hasOwnProperty.call(obj, 'constructor') && obj.constructor.name === 'Promise') 3 | } 4 | -------------------------------------------------------------------------------- /src/methodsPromise.js: -------------------------------------------------------------------------------- 1 | import isObject from './isObject' 2 | import hijack from './hijack' 3 | 4 | export default (opt = {}) => { 5 | // Configure the hook function 6 | if (typeof opt.hookName !== 'string') { 7 | opt.hookName = '$promise' 8 | } 9 | // Global hook function 10 | if (typeof opt.promise !== 'function') { 11 | opt.promise = (mp) => { 12 | mp.catch((err) => { 13 | console.log(err) 14 | }) 15 | } 16 | } 17 | 18 | return { 19 | beforeCreate () { 20 | const { methods } = this.$options 21 | if (!isObject(methods)) return 22 | Object.keys(methods).forEach((k) => { 23 | let fn = methods[k] 24 | if (fn._vueMethodsPromise !== true && typeof fn === 'function' && k !== opt.hookName) { 25 | methods[k] = hijack(opt, fn) 26 | } 27 | }) 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/browser/index.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import jsdom from 'jsdom' 3 | 4 | const browser = () => { // Create a browser 5 | return new Promise((resolve, reject) => { 6 | jsdom.env( 7 | '
', 8 | ['https://cdn.jsdelivr.net/vue/latest/vue.js', './dist/vue-methods-promise.js'], 9 | (err, window) => { 10 | if (err) return reject(err) 11 | resolve(window) 12 | } 13 | ) 14 | }) 15 | } 16 | 17 | test('Page introduction install', (t) => { 18 | return browser().then(({ vueMethodsPromise }) => { 19 | t.true(typeof vueMethodsPromise === 'function') 20 | }) 21 | }) 22 | 23 | test('Global hook promise call', () => { 24 | return browser() 25 | .then(({ Vue, vueMethodsPromise }) => { 26 | return new Promise((resolve, reject) => { 27 | setTimeout(() => reject(new Error('Test timeout')), 3000) 28 | vueMethodsPromise(Vue, { 29 | promise: (mp) => mp.then(resolve) 30 | }) 31 | return new Vue({ 32 | el: '#app', 33 | mounted () { 34 | this.init() 35 | }, 36 | methods: { 37 | init () { 38 | return new Promise((resolve, reject) => resolve()) 39 | } 40 | } 41 | }) 42 | }) 43 | }) 44 | }) 45 | 46 | test('Component hook promise call', () => { 47 | return browser() 48 | .then(({ Vue, vueMethodsPromise }) => { 49 | return new Promise((resolve, reject) => { 50 | setTimeout(() => reject(new Error('Test timeout')), 3000) 51 | vueMethodsPromise(Vue) 52 | return new Vue({ 53 | el: '#app', 54 | mounted () { 55 | this.init() 56 | }, 57 | methods: { 58 | init () { 59 | return new Promise((resolve, reject) => resolve()) 60 | }, 61 | $promise: resolve 62 | } 63 | }) 64 | }) 65 | }) 66 | }) 67 | 68 | test('Component to global hook promise call', () => { 69 | return browser() 70 | .then(({ Vue, vueMethodsPromise }) => { 71 | return new Promise((resolve, reject) => { 72 | setTimeout(() => reject(new Error('Test timeout')), 3000) 73 | vueMethodsPromise(Vue, { 74 | promise: (mp) => mp.then(resolve) 75 | }) 76 | return new Vue({ 77 | el: '#app', 78 | mounted () { 79 | this.init() 80 | }, 81 | methods: { 82 | init () { 83 | return new Promise((resolve, reject) => resolve()) 84 | }, 85 | $promise: (mp) => { 86 | return mp 87 | } 88 | } 89 | }) 90 | }) 91 | }) 92 | }) 93 | 94 | test('Component hook set name', () => { 95 | return browser() 96 | .then(({ Vue, vueMethodsPromise }) => { 97 | return new Promise((resolve, reject) => { 98 | setTimeout(() => reject(new Error('Test timeout')), 3000) 99 | vueMethodsPromise(Vue, { 100 | hookName: '$Promise' 101 | }) 102 | return new Vue({ 103 | el: '#app', 104 | mounted () { 105 | this.init() 106 | }, 107 | methods: { 108 | init () { 109 | return new Promise((resolve, reject) => resolve()) 110 | }, 111 | $Promise: resolve 112 | } 113 | }) 114 | }) 115 | }) 116 | }) 117 | 118 | test('Component hook not loop', () => { 119 | return browser() 120 | .then(({ Vue, vueMethodsPromise }) => { 121 | return new Promise((resolve, reject) => { 122 | setTimeout(() => reject(new Error('Test timeout')), 3000) 123 | vueMethodsPromise(Vue) 124 | return new Vue({ 125 | el: '#app', 126 | mounted () { 127 | this.init() 128 | }, 129 | data () { 130 | return { 131 | count: 0 132 | } 133 | }, 134 | methods: { 135 | init () { 136 | return new Promise((resolve, reject) => resolve()) 137 | }, 138 | $promise (mp) { 139 | this.count++ 140 | setTimeout(() => { 141 | if (this.count === 1) { 142 | resolve() 143 | } else { 144 | reject(new Error('Test loop')) 145 | } 146 | }, 500) 147 | return mp 148 | } 149 | } 150 | }) 151 | }) 152 | }) 153 | }) 154 | 155 | test('Vue methods default return value', () => { 156 | return browser().then(({ Vue, vueMethodsPromise }) => { 157 | return new Promise((resolve, reject) => { 158 | setTimeout(() => reject(new Error('Test timeout')), 3000) 159 | vueMethodsPromise(Vue) 160 | return new Vue({ 161 | el: '#app', 162 | mounted () { 163 | if (this.count() === 100) return resolve() 164 | }, 165 | methods: { 166 | count () { 167 | return 100 168 | } 169 | } 170 | }) 171 | }) 172 | }) 173 | }) 174 | 175 | test('Return value typeof not call hook', () => { 176 | return browser().then(({ Vue, vueMethodsPromise }) => { 177 | return new Promise((resolve, reject) => { 178 | setTimeout(() => resolve(new Error('Test timeout')), 3000) 179 | vueMethodsPromise(Vue, { 180 | promise: (mp) => mp.then(reject) 181 | }) 182 | return new Vue({ 183 | el: '#app', 184 | mounted () { 185 | this.null() 186 | this.int() 187 | this.float() 188 | this.booleanTrue() 189 | this.booleanFalse() 190 | this.array() 191 | this.function() 192 | this.regExp() 193 | this.object() 194 | this.objectConstructors() 195 | this.undefined() 196 | this.arguments() 197 | this.symbol() 198 | this.map() 199 | this.set() 200 | }, 201 | methods: { 202 | null () { 203 | return null 204 | }, 205 | int () { 206 | return 100 207 | }, 208 | float () { 209 | return 0.3 210 | }, 211 | booleanTrue () { 212 | return true 213 | }, 214 | booleanFalse () { 215 | return false 216 | }, 217 | array () { 218 | return [] 219 | }, 220 | function () { 221 | return function () {} 222 | }, 223 | regExp () { 224 | return new RegExp('\\d+') 225 | }, 226 | object () { 227 | return {} 228 | }, 229 | objectConstructors () { 230 | return { 231 | constructor: function Promise () {} 232 | } 233 | }, 234 | undefined () { 235 | return arguments[0] 236 | }, 237 | arguments () { 238 | return arguments 239 | }, 240 | symbol () { 241 | return Symbol('test') 242 | }, 243 | map () { 244 | return new Map() 245 | }, 246 | set () { 247 | return new Set() 248 | } 249 | } 250 | }) 251 | }) 252 | }) 253 | }) 254 | -------------------------------------------------------------------------------- /test/unit/hijack.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import hijack from '../../src/hijack' 3 | 4 | test('Return function', (t) => { 5 | const opt = { 6 | hookName: '$promise', 7 | promise (mp) { 8 | 9 | } 10 | } 11 | const method = hijack(opt, function () { 12 | 13 | }) 14 | t.is(method.name, 'vueMethodsPromise') 15 | t.true(method._vueMethodsPromise) 16 | }) 17 | 18 | test('Component hook promise call', (t) => { 19 | return new Promise((resolve, reject) => { 20 | setTimeout(() => reject(new Error('Test timeout')), 3000) 21 | const opt = { 22 | hookName: '$promise', 23 | promise () { } 24 | } 25 | const method = hijack(opt, function () { 26 | return Promise.resolve(true) 27 | }) 28 | method.call({ 29 | $promise (mp) { 30 | resolve(true) 31 | } 32 | }) 33 | }) 34 | }) 35 | 36 | test('Component hook to global hook promise call', (t) => { 37 | return new Promise((resolve, reject) => { 38 | setTimeout(() => reject(new Error('Test timeout')), 3000) 39 | const opt = { 40 | hookName: '$promise', 41 | promise () { 42 | resolve(true) 43 | } 44 | } 45 | const method = hijack(opt, function () { 46 | return Promise.resolve(true) 47 | }) 48 | method.call({ 49 | $promise (mp) { 50 | return mp 51 | } 52 | }) 53 | }) 54 | }) 55 | 56 | test('Not Global hook promise call', (t) => { 57 | return new Promise((resolve, reject) => { 58 | setTimeout(() => resolve(true), 3000) 59 | const opt = { 60 | hookName: '$promise', 61 | promise () { 62 | reject(new Error('Test fail')) 63 | } 64 | } 65 | const method = hijack(opt, function () { 66 | return Promise.resolve(true) 67 | }) 68 | method.call({ 69 | $promise (mp) { 70 | } 71 | }) 72 | }) 73 | }) 74 | 75 | test('Global hook promise call', (t) => { 76 | return new Promise((resolve, reject) => { 77 | setTimeout(() => reject(new Error('Test timeout')), 3000) 78 | const opt = { 79 | hookName: '$promise', 80 | promise () { 81 | resolve(true) 82 | } 83 | } 84 | const method = hijack(opt, function () { 85 | return Promise.resolve(true) 86 | }) 87 | method.call({}) 88 | }) 89 | }) 90 | 91 | test('Hook return false not global hook promise call', (t) => { 92 | return new Promise((resolve, reject) => { 93 | setTimeout(() => resolve(true), 3000) 94 | const opt = { 95 | hookName: '$promise', 96 | promise () { 97 | reject(new Error('Test fail')) 98 | } 99 | } 100 | const method = hijack(opt, function () { 101 | return false 102 | }) 103 | method.call({}) 104 | }) 105 | }) 106 | -------------------------------------------------------------------------------- /test/unit/isObject.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import isObject from '../../src/isObject' 3 | 4 | test('Yes object', (t) => { 5 | t.true(isObject({})) 6 | }) 7 | 8 | test('Not null', (t) => { 9 | t.false(isObject(null)) 10 | }) 11 | 12 | test('Not true', (t) => { 13 | t.false(isObject(true)) 14 | }) 15 | 16 | test('Not false', (t) => { 17 | t.false(isObject(false)) 18 | }) 19 | 20 | test('Not undefined', (t) => { 21 | t.false(isObject(undefined)) 22 | }) 23 | 24 | test('Not function', (t) => { 25 | t.false(isObject(function () {})) 26 | }) 27 | 28 | test('Not array', (t) => { 29 | t.false(isObject([])) 30 | }) 31 | 32 | test('Not array', (t) => { 33 | t.false(isObject([])) 34 | }) 35 | 36 | test('Not regExp', (t) => { 37 | t.false(isObject(/\./)) 38 | }) 39 | 40 | test('Not class', (t) => { 41 | class Test { 42 | 43 | } 44 | t.false(isObject(Test)) 45 | }) 46 | 47 | test('Not int', (t) => { 48 | t.false(isObject(100)) 49 | }) 50 | 51 | test('Not float', (t) => { 52 | t.false(isObject(100.88)) 53 | }) 54 | 55 | test('Not negative int', (t) => { 56 | t.false(isObject(-100)) 57 | }) 58 | 59 | test('Not negative float', (t) => { 60 | t.false(isObject(-100.88)) 61 | }) 62 | -------------------------------------------------------------------------------- /test/unit/isPromise.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import isPromise from '../../src/isPromise' 3 | 4 | test('Yes new Promise', (t) => { 5 | t.true(isPromise(new Promise((resolve, reject) => resolve()))) 6 | }) 7 | 8 | test('Yes Promise.resolve', (t) => { 9 | t.true(isPromise(Promise.resolve())) 10 | }) 11 | 12 | test('Yes Promise.reject', (t) => { 13 | t.true(isPromise(Promise.reject(new Error('Error test')).catch((err) => err))) 14 | }) 15 | 16 | test('Yes Promise.all', (t) => { 17 | t.true(isPromise(Promise.all([]))) 18 | }) 19 | 20 | test('Yes Promise.race', (t) => { 21 | t.true(isPromise(Promise.race([]))) 22 | }) 23 | 24 | test('Not object', (t) => { 25 | t.false(isPromise({})) 26 | }) 27 | 28 | test('Not object.constructors', (t) => { 29 | t.false(isPromise({ 30 | constructor: function Promise () {} 31 | })) 32 | }) 33 | 34 | test('Not null', (t) => { 35 | t.false(isPromise(null)) 36 | }) 37 | 38 | test('Not true', (t) => { 39 | t.false(isPromise(true)) 40 | }) 41 | 42 | test('Not false', (t) => { 43 | t.false(isPromise(false)) 44 | }) 45 | 46 | test('Not undefined', (t) => { 47 | t.false(isPromise(undefined)) 48 | }) 49 | 50 | test('Not function', (t) => { 51 | t.false(isPromise(function () {})) 52 | }) 53 | 54 | test('Not array', (t) => { 55 | t.false(isPromise([])) 56 | }) 57 | 58 | test('Not array', (t) => { 59 | t.false(isPromise([])) 60 | }) 61 | 62 | test('Not regExp', (t) => { 63 | t.false(isPromise(/\./)) 64 | }) 65 | 66 | test('Not class', (t) => { 67 | class Test { 68 | 69 | } 70 | t.false(isPromise(Test)) 71 | }) 72 | 73 | test('Not int', (t) => { 74 | t.false(isPromise(100)) 75 | }) 76 | 77 | test('Not float', (t) => { 78 | t.false(isPromise(100.88)) 79 | }) 80 | 81 | test('Not negative int', (t) => { 82 | t.false(isPromise(-100)) 83 | }) 84 | 85 | test('Not negative float', (t) => { 86 | t.false(isPromise(-100.88)) 87 | }) 88 | -------------------------------------------------------------------------------- /test/unit/methodsPromise.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import methodsPromise from '../../src/methodsPromise' 3 | import isObject from '../../src/isObject' 4 | 5 | test('Hijack methods', (t) => { 6 | const mixin = methodsPromise() 7 | t.true(isObject(mixin)) 8 | t.is(typeof mixin.beforeCreate, 'function') 9 | t.is(mixin.beforeCreate.name, 'beforeCreate') 10 | const self = { 11 | $options: { 12 | methods: { 13 | test () { 14 | 15 | }, 16 | $promise () { 17 | 18 | }, 19 | name: 'Test', 20 | init () { 21 | 22 | } 23 | } 24 | } 25 | } 26 | self.$options.methods.init._vueMethodsPromise = true 27 | mixin.beforeCreate.call(self) 28 | const methods = self.$options.methods 29 | t.is(methods.test.name, 'vueMethodsPromise') 30 | t.is(methods.name, 'Test') 31 | t.is(methods.$promise.name, '$promise') 32 | t.is(methods.init.name, 'init') 33 | }) 34 | --------------------------------------------------------------------------------