Hi, is there a way to use throw new Error('my custom error');
inside an async method and still have it return the red alert with the custom error message?
Thanks in advance,
Simone
Hi, is there a way to use throw new Error('my custom error');
inside an async method and still have it return the red alert with the custom error message?
Thanks in advance,
Simone
You have to show some context.
Hi robert,
iâm registering the capability âspeaker_playngâ:
this.registerCapabilityListener(âspeaker_playingâ, async (value) => { ⌠}
I would like to insert a timer that throws an error if playback does not start after 5 seconds of pressing the play button:
this.registerCapabilityListener(âspeaker_playingâ, async (value) => {
this.playbackTimer = this.homey.setTimeout(() => {
throw new Error(âPlayback Error!!!â);
}, 5000);
}
Unfortunately trying to throw a custom error from the (async) setTimeout method does not show the homey red alert with the error message.
This wonât work because using a timeout creates a separate context from the capability listener. The error is thrown inside the âtimer contextâ, not the âcapability listener contextâ.
Iâm not sure how you determine if playback has started, but say that you use an (async) method isPlaying()
for that.
In that case, you can use something like this (untested):
const delay = ms => new Promise(resolve => this.homey.setTimeout(resolve, ms));
const timeout = (promise, ms, err) => Promise.race([ promise, delay(ms).then(() => throw Error(err)) ]);
this.registerCapabilityListener('speaker_playing', async (value) => {
await timeout(this.isPlaying(), 5000, 'Playback Error!!!');
}
This is the old âstyleâ timeout, there is now an âofficialâ one.
Not sure why youâre removing the line above it that uses that exact method
Itâs still early in the morning, but in my opinion it should read like this
this.registerCapabilityListener('speaker_playing', async (value) => {
this.homey.setTimeout(this.isPlaying(), 5000, 'Playback Error!!!');
}
Yes, it is. Read back on what the issue is that weâre trying to solve
This is new, but isnât the problem more with the Homey app?
BDW: I had to change all timeouts some time ago because the app no longer closed properly.
No.
My proposed solution is using the SDK timeout implementation:
const delay = ms => new Promise(resolve => this.homey.setTimeout(resolve, ms));
^^^^^^^^^^^^^^^^^^^^^
const timeout = (promise, ms, err) => Promise.race([ promise, delay(ms).then(() => throw Error(err)) ]);
Ok my mistake !!!
And what do we learn from this, first drink coffee and then read & write in the forum, then you donât embarrass yourselfâŚ
Very big SORRY âŚ
Thanks to both of you.
@robertkep I tried to use your code but without success. Iâll give you some more information on the structure of my class.
Iâm working on device.js
in onOnit I define the variable for the timer:
this.playbackTimer = null;
in registerCapabilityListener(âspeaker_playingâ) I set the timer as already indicated:
this.registerCapabilityListener(âspeaker_playingâ, async (value) => {
this.playbackTimer = this.homey.setTimeout(() => {
âŚ
throw new Error(âPlayback Error!!!â);
}, 5000);
}
in an async event that fires when the playback starts I clear the timer:
this.on(âplayerChangedâ, async (playerDetail) => {
âŚ
this.homey.clearTimeout(this.playbackTimer);
}
In this way if the async event is not called or is called after 5 seconds from pressing the play button the timer callback fires, resets the player (and up to this point everything works) but does not return any error alert.
I think you can use something like this:
// a new method that waits for an event until a timeout is reached
waitForEvent(event, timeout) {
return new Promise((resolve, reject) => {
this.once(event, resolve);
this.homey.setTimeout(reject, timeout);
});
}
// to use:
this.registerCapabilityListener('speaker_playing', async (value) => {
try {
const eventData = await this.waitForEvent('playerChanged', 5000);
} catch(e) {
throw Error('Playback Error!!!');
}
});
Thanks Robert! Works like a charm!