Open idoodler opened 4 years ago
Try overriding Q.nextTick
(set requestTick to Promise.resolve().then(fn)
and see if it helps?
@benjamingr No, I opened the Safari Webinspector and executed Q.nextTick = function(fn) { Promise.resolve().then(fn) }
which did not change anything.
There were reports of Safari dropping timer events ages ago. I don’t know whether they went away, but your description of the problem seems to indicate a regression. Apart from looking for a more reliable primitive for timers as @benjamingr hints at, there is not a lot Q can do, and changing the underlying nextTick implementation requires very time consuming testing.
To wit, you can see some of that rigor over on https://github.com/kriskowal/asap, which I’ve not updated in ages.
It may be worthwhile to file an issue against Safari.
I just tried to reproduce this issue with a fresh Cordova project, but I couldn't. The Promise stays alive during the application close and open. Any tips on how to debug this?
This issue is still present on iOS 14 Beta 3.
This issue is still present on iOS 14 Beta 4
After revisiting this issue I decided to add Q.nextTick = function(fn) { Promise.resolve().then(fn) }
in our Application code (not just adding it via the Webinspector). It looks like as if this solves the issue. Does this indicate some errors in our Promise handling?
The issue is still found on iOS 14 Beta 5 (and does not appear to affect iOS 13). Here's what I understand so far:
modern browsers
where setImmediate
is not definedchannel.port2
posts a message, and channel.port1.onmessage
respondsHere's what happens in the background:
channel.port2
posts a messagechannel.port1
misses that message <-- I'll submit this to Apple as a difference in behavior in WKWebView on iOS 13 vs. 14flushing
variable is never toggled from false to true... and no further promises are resolvedIt might be helpful to reproduce and fix the problem in ASAP where we have CI that covers a broad spectrum of browsers. It would need some refreshing.
If we can address the issue in ASAP, it would give us some confidence of a solution that could be back-ported to Q. Alternately, we would need to back-port the testing setup in ASAP to give us the confidence we would need.
FYI, I opened FB8533670 with Apple regarding a change in onmessage
in WKWebView on iPadOS 14 as the App leaves the foreground. My related Apple Developer Forum post is here, for tracking.
Ended up making a temporary patch to q.js:
setTimeout
right before posting a messageflush()
When the posted message is missed, the timeout calls flush()
.
FYI, I opened FB8533670 with Apple regarding a change in
onmessage
in WKWebView on iPadOS 14 as the App leaves the foreground. My related Apple Developer Forum post is here, for tracking.Ended up making a temporary patch to q.js:
- creating a backup
setTimeout
right before posting a message- clearing that timeout in
flush()
When the posted message is missed, the timeout calls
flush()
.
Apple Responded, and says this new behavior is expected: "Promptly suspending when entering the background is correct behavior according to the norm of iOS."
Maybe you can push back on Apple here. Of course it’s expected to suspend in the background. It’s also expected for the message to be delivered when returning to the foreground, unless the page is reloaded entirely. Clearly, this is a case where some timers survive stasis.
Thanks, Kris--I actually sent this yesterday:
I do want to point out that this difference in behavior means that a message posted as the app begins to background will get “lost” rather than “handled” when the app returns to the foreground.
We'll see if we get a response.
We are developing an Cordova based iOS App. Everything works fine on iOS 13, but we experience issues on iOS 14.
Whenever the App is sent to background and retrieved again the app is unresponsive as we use Q.js for our ViewManager.
When debugging this via the Safari Web Inspector I noticed that
var def = Q.defer(); def.promise.done(function(value) { alert(value); }); def.resolve("Done")
works before but not after sending the app to the background. However native Javascript Promises work as expectednew Promise(function(resolve, reject) { resolve("Done"); }).then(function(value) { alert(value) });
When inspecting the
def
variable usingdef.promise.inspect()
the state is resolved and I can see the value, however none of the functions (resolve, reject, finally) are called, neither in the done, nor in the then function.Anyone experience similar issues?
Edit: We are using Q#1.5.1