diff --git a/lib/init.lua b/lib/init.lua index 30d9335..98ceb40 100644 --- a/lib/init.lua +++ b/lib/init.lua @@ -1925,6 +1925,36 @@ function Promise.retry(callback, times, ...) end) end +--[=[ + Repeatedly calls a Promise-returning function up to `times` number of times, waiting `seconds` seconds between each + retry, until the returned Promise resolves. + + If the amount of retries is exceeded, the function will return the latest rejected Promise. + + @since v3.2.0 + @param callback (...: P) -> Promise + @param times number + @param seconds number + @param ...? P +]=] +function Promise.retryWithDelay(callback, times, seconds, ...) + assert(isCallable(callback), "Parameter #1 to Promise.retry must be a function") + assert(type(times) == "number", "Parameter #2 (times) to Promise.retry must be a number") + assert(type(seconds) == "number", "Parameter #3 (seconds) to Promise.retry must be a number") + + local args, length = { ... }, select("#", ...) + + return Promise.resolve(callback(...)):catch(function(...) + if times > 0 then + Promise.delay(seconds):await() + + return Promise.retryWithDelay(callback, times - 1, seconds, unpack(args, 1, length)) + else + return Promise.reject(...) + end + end) +end + --[=[ Converts an event into a Promise which resolves the next time the event fires. diff --git a/lib/init.spec.lua b/lib/init.spec.lua index 7b86d44..5f0a936 100644 --- a/lib/init.spec.lua +++ b/lib/init.spec.lua @@ -1611,6 +1611,37 @@ return function() end) end) + describe("Promise.retryWithDelay", function() + it("should retry after a delay", function() + local counter = 0 + + local promise = Promise.retryWithDelay(function(parameter) + expect(parameter).to.equal("foo") + + counter = counter + 1 + + if counter == 3 then + return Promise.resolve("ok") + end + + return Promise.reject("fail") + end, 3, 10, "foo") + + expect(counter).to.equal(1) + + advanceTime(11) + + expect(counter).to.equal(2) + + advanceTime(11) + + expect(counter).to.equal(3) + + expect(promise:getStatus()).to.equal(Promise.Status.Resolved) + expect(promise._values[1]).to.equal("ok") + end) + end) + describe("Promise.fromEvent", function() it("should convert a Promise into an event", function() local event = Instance.new("BindableEvent")