For show how promise and deferred work, we create a new and simple promise and deferred object, so that you can easy understand it.
Promise Object
Here try to extend EventEmitter module to explain how it work. Promise.class.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classPromiseextendsEventEmitter{ then(success, error, progress) { if (typeof success === 'function') { this.once('success', success) } if (typeof error === 'function') { this.once('error', error) } if (typeof progress === 'progress') { // Note, this function will be recall, so here defined the event use 'on' this.on('progress', progress) } } }
Here you can see we defined three events after you pass these callback function into it through ‘then’ function. So we defined the events, and we have to trigger it, so that we can execute these callbacks with the result.
Below, we defined the Deferred object.
Deferred Object
Here we defined the Deferred, these functions just emit promise, so tell them we finished. Deferred.class.js
To implement this, we create a new Deferred, and we trigger deferred function (progress/end/error) when we finish specific action to tell Deferred that we finished. Then we get promise object, and then we can store it, and call it with callback in another file. So we successful separate call async and get data in two files.
// in another file, this just an example to pass the result to global, so we can easy get the result, in the production, you better to pass the result in other way. global.result.then((result) => { // success }, (err) => { // error }, (chunk) => { // progress console.log(chunk) })
Deferred.all()
Do some action after a several of asynchronous finished. Deferred.class.js
resolve(data) { let promise = this.promise let handler while(handler = promise.queue.shift()) { if (handler && handler.resolve) { let ret = handler.resolve(data)
// if there has next promise, then we interrupt current loop, and set next promise.queue equals current queue if (ret && ret.isPromise) { ret.queue = promise.queue return } } } }
reject(err) { let promise = this.promise let handler while(handler = promise.queue.shift()) { if (handler && handler.reject) { let ret = handler.reject(err)
// if there has next promise, then we interrupt current loop, and set next promise.queue equals current queue if (ret && ret.isPromise) { ret.queue = promise.queue return } } } }
callback(str) { let that = this return(err, file) => { if (err) { return that.reject(err) } that.resolve(file) } } }