Guest User

Untitled

a guest
Aug 14th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.96 KB | None | 0 0
  1. local Promise = {}
  2. Promise.__index = Promise
  3.  
  4. Promise.State = {
  5. Pending = 'Pending',
  6. Resolved = 'Resolved',
  7. Rejected = 'Rejected',
  8. }
  9.  
  10. function Promise.new(func)
  11. local self = {
  12. state = Promise.State.Pending,
  13. value = nil,
  14. reason = nil,
  15. onResolved = {},
  16. onRejected = {},
  17. }
  18. setmetatable(self, Promise)
  19.  
  20. local function resolve(value)
  21. if self.state ~= Promise.State.Pending then
  22. error("Cannot resolve non-pending promise", 1)
  23. end
  24. self.value = value
  25. self.state = Promise.State.Resolved
  26. for callback in pairs(self.onResolved) do
  27. callback(value)
  28. end
  29. end
  30.  
  31. local function reject(reason)
  32. if self.state ~= Promise.State.Pending then
  33. error("Cannot reject non-pending promise", 1)
  34. end
  35. self.reason = reason
  36. self.state = Promise.State.Rejected
  37. for callback in pairs(self.onRejected) do
  38. callback(reason)
  39. end
  40. end
  41.  
  42. func(resolve, reject)
  43.  
  44. return self
  45. end
  46.  
  47. function Promise:andThen(onResolve, onReject)
  48. return Promise.new(function(resolveChild, rejectChild)
  49. local function resolveCallback(value)
  50. local newValue = value
  51. if onResolve then
  52. newValue = onResolve(newValue)
  53. end
  54. if type(newValue) == 'table' and newValue.andThen then
  55. newValue:andThen(resolveChild, rejectChild)
  56. else
  57. resolveChild(newValue)
  58. end
  59. end
  60.  
  61. local function rejectCallback(reason)
  62. local newReason = reason
  63. if onReject then
  64. newReason = onReject(newReason)
  65. end
  66. if type(newReason) == 'table' and newReason.andThen then
  67. newReason:andThen(resolveChild, rejectChild)
  68. else
  69. rejectChild(newReason)
  70. end
  71. rejectChild(newReason)
  72. end
  73.  
  74. if self.state == Promise.State.Resolved then
  75. resolveCallback(self.value)
  76. elseif self.state == Promise.State.Rejected then
  77. rejectCallback(self.reason)
  78. else
  79. self.onResolved[resolveCallback] = true
  80. self.onRejected[rejectCallback] = true
  81. end
  82. end)
  83. end
  84.  
  85. -- Doesn't work on the main task in Roblox until Brad's changes go live
  86. function Promise:wait()
  87. local thread = coroutine.running()
  88. if self.state == Promise.State.Resolved then
  89. return true, self.value
  90. elseif self.state == Promise.State.Rejected then
  91. return false, self.reason
  92. else
  93. self:andThen(
  94. function(value)
  95. return coroutine.resume(thread, true, value)
  96. end,
  97. function(reason)
  98. return coroutine.resume(thread, false, reason)
  99. end
  100. )
  101. return coroutine.yield()
  102. end
  103. end
  104.  
  105. local tests = {}
  106.  
  107. function tests.worksAtAll()
  108. local promise = Promise.new(function(resolve, _) resolve(4) end)
  109. local result = promise
  110. :andThen(function(value) return value + 1 end)
  111. :andThen(function(value) assert(value == 5) return value end)
  112. return result
  113. end
  114.  
  115. function tests.nonImmediateResolve()
  116. local resolveFunc
  117. local promise = Promise.new(function(resolve, _) resolveFunc = resolve end)
  118. local result = promise
  119. :andThen(function(value) return value + 1 end)
  120. :andThen(function(value) assert(value == 5) return value end)
  121.  
  122. assert(result.state == Promise.State.Pending)
  123. resolveFunc(4)
  124. assert(result.state == Promise.State.Resolved)
  125.  
  126. return result
  127. end
  128.  
  129. function tests.promiseReturningPromise()
  130. local promise =
  131. Promise.new(function(resolve, _) resolve(4) end)
  132. :andThen(function(value)
  133. return Promise.new(function(resolve, _) resolve(value + 1) end)
  134. end)
  135. :andThen(function(value) assert(value == 5) return value end)
  136.  
  137. return promise
  138. end
  139.  
  140. function tests.promiseReturningPromiseNonImmediate()
  141. local resolveFunc
  142. local promise =
  143. Promise.new(function(resolve, _) resolveFunc = resolve end)
  144. :andThen(function(value)
  145. return Promise.new(function(resolve, _) resolve(value + 1) end)
  146. end)
  147. :andThen(function(value) assert(value == 5) return value end)
  148.  
  149. resolveFunc(4)
  150.  
  151. return promise
  152. end
  153.  
  154. local function printStatus(ok, name, value)
  155. local status = ok and "PASSED" or "FAILED"
  156. print(string.format("[%s] %s", status, name))
  157. print(value)
  158. end
  159.  
  160. for name, func in pairs(tests) do
  161. local promise = func()
  162. promise:andThen(
  163. function(value)
  164. printStatus(true, name, value)
  165. end,
  166. function(reason)
  167. printStatus(false, name, reason)
  168. end
  169. )
  170. end
  171.  
  172. return Promise
Add Comment
Please, Sign In to add comment