Skip to content

Instantly share code, notes, and snippets.

@lqt0223
Last active May 30, 2017 12:11
Show Gist options
  • Save lqt0223/50dff7bb317aea41764f9557bcdc1529 to your computer and use it in GitHub Desktop.
Save lqt0223/50dff7bb317aea41764f9557bcdc1529 to your computer and use it in GitHub Desktop.
Promise implementation
// Promise Implemenetation
// SOME CONSTANT
var https = require('https')
var URL1 = "https://jsonplaceholder.typicode.com/posts?userId="
var URL2 = "https://jsonplaceholder.typicode.com/posts?id="
// Phase 1: make function in 'then' deferred, and callback with resolved data later
// TEST
var timeout = function(ms) {
return new _Promise1(function(resolve) {
setTimeout(function() {
resolve("test data")
}, ms)
})
}
timeout(2000).then(function(data){
console.log(data)
})
// IMPLEMENTATION
function _Promise1(handler) {
this.then = function(deferred){
this.deferred = deferred
}
handler((data) => {
this.deferred(data)
})
}
// Phase 2: chaining promise, and passing resolved data using return
// TEST
var get = function(url) {
return new _Promise2(function(resolve) {
https.get(url, (res) => {
var buffer = new Buffer([])
res.on("data", (data) => {
buffer = Buffer.concat([buffer, data])
})
res.on("end", () => {
resolve(buffer.toString())
})
})
})
}
get(URL1 + "2").then(function(data){
var posts = JSON.parse(data)
var lastPost = posts[posts.length - 1]
var lastId = lastPost.id
return lastId
}).then(function(id) {
get(URL2 + id).then(function(data) {
console.log(data)
})
})
// IMPLEMENTATION
function _Promise2(handler){
this.deferred = []
this.transferred
this.then = function(deferred) {
this.deferred.push(deferred)
return this
}
handler((data) => {
this.transferred = data
while(this.deferred.length > 0){
var deferred = this.deferred.shift()
this.transferred = deferred(this.transferred)
}
})
}
// Phase 3: pass on Promise object using return and get resolved value in the next then call (with refractoring)
// TEST
var get = function(url) {
return new _Promise3(function(resolve) {
https.get(url, (res) => {
var buffer = new Buffer([])
res.on("data", (data) => {
buffer = Buffer.concat([buffer, data])
})
res.on("end", () => {
resolve(buffer.toString())
})
})
})
}
get(URL1 + "3").then(function(data){
var posts = JSON.parse(data)
var lastPost = posts[posts.length - 1]
var lastId = lastPost.id
return lastId
})
.then(function(id) {
return (URL2 + id)
})
.then(function(url) {
return get(url)
})
.then(function(response){
return response.slice(1,200)
})
.then(function(sliced) {
return sliced.match("\"userId\":.*,")[0]
})
.then(function(userId) {
return userId.slice(10,-1)
})
.then(function(userId) {
var newUserId = parseInt(userId) + 2
return get(URL1 + newUserId)
})
.then(function(res) {
console.log(res)
})
// IMPLEMENTATION
function _Promise3(handler){
var self = this
// the array for deferred callbacks
this.deferred = []
// implement a internal resolve function that can resolve a promise object and callback result
function _resolve(promise, callback){
promise.then(function(data){
callback(data)
})
}
// recursively call this to invoke deferred handlers,
// and when the passed on value is a promise object,
// resolve it before the next deferred handler
function resolveDeferred() {
if(self.deferred.length == 0) return
var deferred = self.deferred.shift()
if(isPromise(self.passOn)) {
_resolve(self.passOn, function(_data) {
self.passOn = deferred(_data)
resolveDeferred()
})
}else{
self.passOn = deferred(self.passOn)
resolveDeferred()
}
}
function getClassName(obj){
var pattern = /function .*\(/
return obj.constructor.toString().match(pattern)[0].slice(9, -1)
}
function isPromise(object) {
if(typeof object != "object") return false
var className = getClassName(self)
var objClassName = getClassName(object)
return className == objClassName
}
this.then = function(deferred) {
this.deferred.push(deferred)
return this
}
// when a new promise object is instantiated,
// the handler function will be immediately invoked,
// resolve deferred in sequence.
handler((data) => {
// the variable for data that is passed on by return in 'then' function
this.passOn = data
resolveDeferred()
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment