Your inquiry involves multiple subquestions, all of which are excellent. To provide comprehensive assistance, it is advisable to address each question individually. I will do my best to offer explanations that can aid in resolving your issue.
first_spec.ts
it('promise chain 1', function () {
/* Displays the following:
[TRACE] default - Start
[DEBUG] default - Sleeping for 100 ms...
[TRACE] default - End
[INFO] default - --1
[DEBUG] default - Sleeping for 200 ms...
[INFO] default - --2
[DEBUG] default - Sleeping for 300 ms...
[INFO] default - --3
[INFO] default - --done
*/
logger.trace("Start");
printLater("--1", 100).then(() => {
printLater("--2", 200).then(() => {
printLater("--3", 300).thenFinally(() => {
logger.info("--done");
});
});
});
logger.trace("End");
});
This section is fairly straightforward. The printLater function returns a promise involving browser.sleep, requiring completion before advancing to the next step. There should be no confusion regarding this specific 'it' block.
it('promise chain 1.1', function () {
/* Displays the following:
[TRACE] default - Start
[DEBUG] default - Sleeping for 100 ms...
[TRACE] default - End
[INFO] default - --1
*/
logger.trace("Start");
nativePromise("--1", 100).then(() => {
nativePromise("--2", 200).then(() => {
nativePromise("--3", 300).finally(() => {
logger.info("--done");
});
});
});
logger.trace("End");
});
In the scenario presented above, the nativePromise function generates a Promise object by calling printLater within it. Here's how the process unfolds: Upon invoking the nativePromise function, it immediately produces a promise object in the pending state. Subsequently using 'then' on nativePromise anticipates a resolve/reject state, but since it remains pending indefinitely until test timeout, the testing halts at some point without any progress. Notably, we still receive output from the first nativePromise due to its asynchronous behavior through the printLater function.
To mimic the behavior of the initial 'it' block, a slight adjustment must be made to the nativePromise function. It becomes imperative to utilize 'resolve' to ensure proper resolution of the promise.
function nativePromise(msg, time) {
return new Promise((resolve) => {
resolve(printLater(msg, time));
});
}
Note: It is always considered a best practice to properly resolve/reject promises.
it('await promise 3.1', async function () {
/* Displays the following:
[TRACE] default - Start
[DEBUG] default - Sleeping for 100 ms...
[INFO] default - --1
*/
await logger.trace("Start");
await nativePromise("--1", 100);
await nativePromise("--2", 200); // Halts after "--1"
await nativePromise("--3", 300);
await logger.info("--done");
await logger.trace("End");
});
The rationale behind the aforementioned code snippet aligns with the earlier explanation. 'await' also waits for the resolution/rejection of promises. Should it fail to return anything, 'await' too gets stuck at a certain juncture.
We integrate 'await' to enhance code clarity, ensuring that it waits for promise resolution/rejection without returning the promise object itself. Instead, 'await' extracts the value directly from the promise object and returns it.
Note1: Jasmine's 'expect' function holds off action until the control flow is clear refer to this link from Protractor
Note2: Protractor Promise (recognized as webdriver.Promise) has been deprecated in Protractor and webdriverJs. Hence, avoiding their usage is advisable whenever possible.