diff --git a/README.md b/README.md index ef1f1af..10bf6e4 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ You can [head to the docs](#docs) for a full treatment of the API. + [TesseractJob.progress(callback: function) -> TesseractJob](#tesseractjobprogresscallback-function---tesseractjob) + [TesseractJob.then(callback: function) -> TesseractJob](#tesseractjobthencallback-function---tesseractjob) + [TesseractJob.catch(callback: function) -> TesseractJob](#tesseractjoberrorcallback-function---tesseractjob) + + [TesseractJob.finally(callback: function) -> TesseractJob](#tesseractjobfinallycallback-function---tesseractjob) * [Local Installation](#local-installation) + [corePath](#corepath) + [workerPath](#workerpath) @@ -80,7 +81,7 @@ Figures out what words are in `image`, where the words are in `image`, etc. + include properties that override some subset of the [default tesseract parameters](./docs/tesseract_parameters.md) + include a `lang` property with a value from the [list of lang parameters](./docs/tesseract_lang_list.md) -Returns a [TesseractJob](#tesseractjob) whose `then`, `progress`, and `catch` methods can be used to act on the result. +Returns a [TesseractJob](#tesseractjob) whose `then`, `progress`, `catch` and `finally` methods can be used to act on the result. ### Simple Example: ```javascript @@ -111,7 +112,7 @@ Figures out what script (e.g. 'Latin', 'Chinese') the words in image are writte - `image` is any [ImageLike](#imagelike) object. -Returns a [TesseractJob](#tesseractjob) whose `then`, `progress`, and `error` methods can be used to act on the result of the script. +Returns a [TesseractJob](#tesseractjob) whose `then`, `progress`, `error` and `finally` methods can be used to act on the result of the script. ```javascript @@ -146,25 +147,28 @@ In NodeJS, an image can be ## TesseractJob -A TesseractJob is an an object returned by a call to `recognize` or `detect`. It's inspired by the ES6 Promise interface and provides `then` and `catch` methods. One important difference is that these methods return the job itself (to enable chaining) rather than new. +A TesseractJob is an an object returned by a call to `recognize` or `detect`. It's inspired by the ES6 Promise interface and provides `then` and `catch` methods. It also provides `finally` method, which will be fired regardless of the job fate. One important difference is that these methods return the job itself (to enable chaining) rather than new. Typical use is: ```javascript Tesseract.recognize(myImage) - .progress(function(message){console.log(message)}) - .catch(function(err){console.error(err)}) - .then(function(result){console.log(result)}) + .progress(message => console.log(message)) + .catch(err => console.error(err)) + .then(result => console.log(result)) + .finally(resultOrError => console.log(resultOrError)) ``` Which is equivalent to: ```javascript var job1 = Tesseract.recognize(myImage); -job1.progress(function(message){console.log(message)}); +job1.progress(message => console.log(message)); -job1.catch(function(err){console.error(err)}); +job1.catch(err => console.error(err)); -job1.then(function(result){console.log(result)}) +job1.then(result => console.log(result)); + +job1.finally(resultOrError => console.log(resultOrError)); ``` @@ -225,6 +229,10 @@ result is: { Sets `callback` as the function that will be called if the job fails. - `callback` is a function with the signature `callback(error)` where `error` is a json object. +### TesseractJob.finally(callback: function) -> TesseractJob +Sets `callback` as the function that will be called regardless if the job fails or success. +- `callback` is a function with the signature `callback(resultOrError)` where `resultOrError` is a json object. + ## Local Installation In the browser, `tesseract.js` simply provides the API layer. Internally, it opens a WebWorker to handle requests. That worker itself loads code from the Emscripten-built `tesseract.js-core` which itself is hosted on a CDN. Then it dynamically loads language files hosted on another CDN. diff --git a/examples/node/basic.js b/examples/node/basic.js index 0593892..e881383 100644 --- a/examples/node/basic.js +++ b/examples/node/basic.js @@ -3,6 +3,12 @@ var Tesseract = require('../../') // replace this with require('tesseract.js') var image = path.resolve(__dirname, 'cosmic.png'); Tesseract.recognize(image) -.then(function(data){ - console.log(data.text) -}) \ No newline at end of file +.then(data => { + console.log('then\n', data.text) +}) +.catch(err => { + console.log('catch\n', err); +}) +.finally(data => { + console.log('finally\n', data.text); +}); \ No newline at end of file diff --git a/src/common/job.js b/src/common/job.js new file mode 100644 index 0000000..3d26f38 --- /dev/null +++ b/src/common/job.js @@ -0,0 +1,81 @@ +const adapter = require('../node/index.js') + +let jobCounter = 0; + +module.exports = class TesseractJob { + constructor(instance){ + this.id = 'Job-' + (++jobCounter) + '-' + Math.random().toString(16).slice(3, 8) + + this._instance = instance; + this._resolve = [] + this._reject = [] + this._progress = [] + this._finally = [] + } + + then(resolve, reject){ + if(this._resolve.push){ + this._resolve.push(resolve) + }else{ + resolve(this._resolve) + } + + if(reject) this.catch(reject); + return this; + } + catch(reject){ + if(this._reject.push){ + this._reject.push(reject) + }else{ + reject(this._reject) + } + return this; + } + progress(fn){ + this._progress.push(fn) + return this; + } + finally(fn) { + this._finally.push(fn) + return this; + } + _send(action, payload){ + adapter.sendPacket(this._instance, { + jobId: this.id, + action: action, + payload: payload + }) + } + + _handle(packet){ + var data = packet.data; + let runFinallyCbs = false; + + if(packet.status === 'resolve'){ + if(this._resolve.length === 0) console.debug(data); + this._resolve.forEach(fn => { + var ret = fn(data); + if(ret && typeof ret.then == 'function'){ + console.warn('TesseractJob instances do not chain like ES6 Promises. To convert it into a real promise, use Promise.resolve.') + } + }) + this._resolve = data; + this._instance._dequeue() + runFinallyCbs = true; + }else if(packet.status === 'reject'){ + if(this._reject.length === 0) console.error(data); + this._reject.forEach(fn => fn(data)) + this._reject = data; + this._instance._dequeue() + runFinallyCbs = true; + }else if(packet.status === 'progress'){ + this._progress.forEach(fn => fn(data)) + }else{ + console.warn('Message type unknown', packet.status) + } + + if (runFinallyCbs) { + this._finally.forEach(fn => fn(data)); + } + } +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 57b00f7..b3b781a 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,6 @@ const adapter = require('./node/index.js') const circularize = require('./common/circularize.js') +const TesseractJob = require('./common/job'); const objectAssign = require('object-assign'); function create(workerOptions){ @@ -75,75 +76,6 @@ class TesseractWorker { } } -var jobCounter = 0; - -class TesseractJob { - constructor(instance){ - this.id = 'Job-' + (++jobCounter) + '-' + Math.random().toString(16).slice(3, 8) - - this._instance = instance; - this._resolve = [] - this._reject = [] - this._progress = [] - } - - then(resolve, reject){ - if(this._resolve.push){ - this._resolve.push(resolve) - }else{ - resolve(this._resolve) - } - - if(reject) this.catch(reject); - return this; - } - catch(reject){ - if(this._reject.push){ - this._reject.push(reject) - }else{ - reject(this._reject) - } - return this; - } - progress(fn){ - this._progress.push(fn) - return this; - } - _send(action, payload){ - adapter.sendPacket(this._instance, { - jobId: this.id, - action: action, - payload: payload - }) - } - - _handle(packet){ - var data = packet.data; - if(packet.status === 'resolve'){ - if(this._resolve.length === 0) console.debug(data); - this._resolve.forEach(fn => { - var ret = fn(data); - if(ret && typeof ret.then == 'function'){ - console.warn('TesseractJob instances do not chain like ES6 Promises. To convert it into a real promise, use Promise.resolve.') - } - }) - this._resolve = data; - this._instance._dequeue() - }else if(packet.status === 'reject'){ - if(this._reject.length === 0) console.error(data); - this._reject.forEach(fn => fn(data)) - this._reject = data; - this._instance._dequeue() - }else if(packet.status === 'progress'){ - this._progress.forEach(fn => fn(data)) - }else{ - console.warn('Message type unknown', packet.status) - } - } -} - - var DefaultTesseract = create() -module.exports = DefaultTesseract - +module.exports = DefaultTesseract \ No newline at end of file