Add Promise.retry

Closes #16
This commit is contained in:
Eryn Lynn 2020-05-29 02:10:29 -04:00
parent 8cb4b21f60
commit e5843cf5a2
3 changed files with 69 additions and 0 deletions

View file

@ -349,6 +349,26 @@ docs:
returns: Promise<array<U>>
static: true
- name: retry
desc: |
Repeatedly calls a Promise-returning function up to `times` number of times, until the returned Promise resolves.
If the amount of retries is exceeded, the function will return the latest rejected Promise.
params:
- name: callback
type:
kind: function
params: "...: P"
returns: Promise<T>
- name: times
type: number
- name: "..."
type: "P"
optional: true
returns: Promise<T>
static: true
- name: is
desc: Checks whether the given object is a Promise via duck typing. This only checks if the object is a table and has an `andThen` method.
static: true

View file

@ -1323,4 +1323,22 @@ function Promise.prototype:now(rejectionValue)
end
end
--[[
Retries a Promise-returning callback N times until it succeeds.
]]
function Promise.retry(callback, times, ...)
assert(type(callback) == "function", "Parameter #1 to Promise.retry must be a function")
assert(type(times) == "number", "Parameter #2 to Promise.retry must be a number")
local args, length = {...}, select("#", ...)
return Promise.resolve(callback(...)):catch(function(...)
if times > 0 then
return Promise.retry(callback, times - 1, unpack(args, 1, length))
else
return Promise.reject(...)
end
end)
end
return Promise

View file

@ -1410,4 +1410,35 @@ return function()
expect(innerPromise:getStatus()).to.equal(Promise.Status.Cancelled)
end)
end)
describe("Promise.retry", function()
it("should retry N times", function()
local counter = 0
local promise = Promise.retry(function(parameter)
expect(parameter).to.equal("foo")
counter = counter + 1
if counter == 5 then
return Promise.resolve("ok")
end
return Promise.reject("fail")
end, 5, "foo")
expect(promise:getStatus()).to.equal(Promise.Status.Resolved)
expect(promise._values[1]).to.equal("ok")
end)
it("should reject if threshold is exceeded", function()
local promise = Promise.retry(function()
return Promise.reject("fail")
end, 5)
expect(promise:getStatus()).to.equal(Promise.Status.Rejected)
expect(promise._values[1]).to.equal("fail")
end)
end)
end