Current Checkout Design
When we toggle delivery method via radio input, once clicked, there’re three sequential HTTP request sent to backend:
When we click the shipping method, there will be three serial HTTP requests sent to the background.
The behavior of this serial request can be clearly seen from the timing diagram of Chrome Developer Tools.
Request1: HTTP PUT to set delivery mode
This HTTP put request is used to modify the delivery mode of the order.
this request is triggered in delivery-mode.component.ts, method changeMode.
The mode modification is triggered from the setDeliveryMode of the service class.
The call will be delegated to service class below:
Request2: HTTP get to load [Multi Cart] Multi Cart Data
This HTTP GET request is triggered in code: checkout.effect.ts, after previous HTTP PUT request is finished successfully:
After the HTTP PUT is executed, reload Cart:
Request 3: HTTP get to load [Checkout] Checkout Details
https://20.83.184.244:9002/occ/v2/electronics-spa/users/current/carts/00002735?fields=deliveryAddress(FULL),deliveryMode,paymentInfo(FULL)&lang=en&curr=USD
trigged in checkout-details.service.ts, line 59.
When 2nd HTTP request is finished, cart is stable again, so trigger loadCheckoutDetails method.
After the Cart is successfully loaded (stable), load the checkout Detail data:
Current design flaws
The problem of current design
Let’s have a look at checkout-delivery.service.ts.
When a user toggles the delivery mode radio input, it DOES NOT mean the HTTP GET request will be sent to backend automatically.
The semantic meaning of line 244 below is: HTTP PUT request could NOT be fired, unless both prerequisites are fulfilled:
- Cart is stable
- Check out loading is finished.
The behavior of executing setDeliveryMode through Actions is protected and executed only when Cart is stable and isLoading is false:
The happy path:
15:42:31 355 user toggles with standard delivery mode
15:42:31 360 since cart is stable, checkout loading is false, so fire HTTP PUT request
15:43:31 361 HTTP PUT request is fired
In happy path, HTTP PUT request is fired almost immediately after user clicks radio input.
There will be problems when testing under a 3G slow network.
Test under slow 3G network, we have trouble now.
Scene scene
- Move to delivery mode page. Standard Delivery radio input is selected.
- Click “Premium Delivery”. Radio input is disabled – works as expected.
- Radio input is enabled – works as expected
- Toggle back to “Standard Delivery”.
Expected behavior: radio input is disabled again.
Current behavior: radio input is NOT disabled.
The following is time sequence after standard delivery input is clicked again ( test step 4 described above )
- 15:45:57 User clicks “Standard delivery”
- 15:45:57 isStable is false, since at this time, the cart load HTTP GET request for previously selected premium Delivery mode is still on the way.
- 15:45:59 the 2nd HTTP GET request has finished.
- 15:45:59 The 3rd HTTP GET request ( Load checkout detail )for previously selected premium Delivery mode is fired.
- 15:45:59 two seconds passed after user clicks “Standard delivery”, but HTTP PUT request still could not be fired, since isStable = false
- XHR log
- Cart is stable now, isLoading = true, since 3rd HTTP GET request is still on the way.
- 3rd HTTP GET request for previously selected premium Delivery mode has finished.
- 15:46: 02 Cart is stable, isLoading = false. OK, now it’s time to fire HTTP PUT request for “standard delivery”.
Totally 5 seconds passed after user clicks “standard delivery”, unfortunately.
Currently, we disable radio input by deliveryModeSetInProcoess$. However, its value could only be changed when there’s a HTTP PUT request sent to
backend.
The value of deliveryModeSetInProcoess$ can be modified only after the HTTP put operation is sent.
deliveryModeSetInProcess$ = this.checkoutDeliveryService
.getSetDeliveryModeProcess()
.pipe(map((state) => state.loading));
And HTTP put has two external dependencies:
As explained above, HTTP PUT request sending has two external dependencies:
- Cart is stable
- Checkout loading has finished.
This means it’s not safe to lock UI by simply using deliveryModeSetInProcess$.
The three requests above the red line in the figure below represent HTTP requests after clicking Standard Delivery.
In general, the 1~3 HTTP requests above the red line in picture below represent the requests sent for Standard Delivery radio input click.
The three requests below the red line in the figure below represent HTTP requests after clicking Standard Delivery.
the 1~3 HTTP requests below the red line for Premium Delivery radio input click.
If user clicks Premimu Delivery radio input after timestamp t1, that is, after 3rd HTTP request for Standard Delivery is finished, we are safe.
If the user clicks on Premium Delivery after the t1 timestamp, this time is safe.
Below is a happy path: t2 > t1
Bad path:
T0: HTTP PUT request has finished. Radio input is enabled again.
If user clicks radio input between (t0, t1), user can toggle between radio input multiple times, however no HTTP put request would be sent( cart should be stable, checkout loading should be false )
Based on Jerry’s observation: such HTTP put request will be queued and sent automatically until cartStable = true and checkout loading = false again.Any user clicks after t1 will lead to concurrent HTTP PUT request sent to backend.
Conversely: Switch input before t1. At this time, the input radio cannot be locked, but the click will not directly trigger the HTTP PUT operation, but will be added to the queue. Then when t1 arrives, these requests are sent out in a concurrent manner like a runaway page number.
Time sequence of Jerry’s testing
Test preparation: Premium Delivery is selected. Let’s say wait 20 seconds until all three HTTP request for it ( 1 PUT and 2 GET ) have finished.
Test sequence:
- Select “Standard delivery”. Radio input is disabled. Works as expected.
- Wait till Radio input is enabled again. Works as expected.
- Select “Premium delivery”. Due to issue, radio input is not disabled any more. At this time, click “Standard delivery” immediately.
Explain on the console.log:
Part1: radio input is disabled. HTTP put request is sent.
Part2: radio input is enabled again.
Part3: 16:57:02 HTTP GET request for “standard mode” is fired.
16:57:03 user clicks “premium delivery”. No HTTP PUT request will be sent.
Part4: 16:57:04 “standard delivery” is selected. No HTTP put request is sent.
Part5: Only once CartStable becomes true and isLoading becomes false, the HTTP put requests are sent now.
The concurrent HTTP put request itself does not make an error, but it will cause the subsequent HTTP GET operation to return an error.
Concurrent HTTP PUT will cause errors in backend API execution:
More original articles by Jerry, all in: "Wang Zixi":
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。