Replace $.ajax() calls with browser-native window.fetch() calls. (#36275)

This commit is contained in:
Atanas Penchev 2023-01-30 07:48:20 +02:00 committed by GitHub
parent 9be843422d
commit 6c053d3eec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 194 additions and 73 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: update
Replace $.ajax() calls with browser-native window.fetch() calls.

View File

@ -167,16 +167,16 @@
if ( attributes.count && attributes.count === attributes.chosenCount ) {
if ( form.useAjax ) {
if ( form.xhr ) {
form.xhr.abort();
if ( form.controller ) {
form.controller.abort();
}
form.$form.block( { message: null, overlayCSS: { background: '#fff', opacity: 0.6 } } );
currentAttributes.product_id = parseInt( form.$form.data( 'product_id' ), 10 );
currentAttributes.custom_data = form.$form.data( 'custom_data' );
form.xhr = $.ajax( {
const options = {
url: wc_add_to_cart_variation_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'get_variation' ),
type: 'POST',
data: currentAttributes,
data: $.param( currentAttributes ),
success: function( variation ) {
if ( variation ) {
form.$form.trigger( 'found_variation', [ variation ] );
@ -199,7 +199,25 @@
complete: function() {
form.$form.unblock();
}
} );
};
const controller = new AbortController();
form.controller = controller;
window.fetch( options.url, {
method: options.type,
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
body: options.data,
signal: controller.signal
} )
.then( response => {
if ( !response.ok ) {
throw new Error( response.statusText );
}
return response.json();
})
.then( options.success )
.finally( () => options.complete() );
} else {
form.$form.trigger( 'update_variation_values' );

View File

@ -51,7 +51,21 @@ jQuery( function( $ ) {
}
};
$.ajax( this.requests[0] );
const options = this.requests[0];
window.fetch( options.url, {
method: options.type,
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
body: options.data
} )
.then( response => {
if ( !response.ok ) {
throw new Error( response.statusText );
}
return response.json();
} )
.then( options.success )
.catch( error => options.error && options.error() )
.finally( () => options.complete && options.complete() );
};
/**
@ -95,7 +109,7 @@ jQuery( function( $ ) {
e.data.addToCartHandler.addRequest({
type: 'POST',
url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'add_to_cart' ),
data: data,
data: $.param( data ),
success: function( response ) {
if ( ! response ) {
return;
@ -139,9 +153,9 @@ jQuery( function( $ ) {
e.data.addToCartHandler.addRequest({
type: 'POST',
url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'remove_from_cart' ),
data: {
data: new URLSearchParams( {
cart_item_key : $thisbutton.data( 'cart_item_key' )
},
} ).toString(),
success: function( response ) {
if ( ! response || ! response.fragments ) {
window.location = $thisbutton.attr( 'href' );

View File

@ -38,9 +38,9 @@ jQuery( function( $ ) {
var $fragment_refresh = {
url: wc_cart_fragments_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'get_refreshed_fragments' ),
type: 'POST',
data: {
data: new URLSearchParams( {
time: new Date().getTime()
},
} ).toString(),
timeout: wc_cart_fragments_params.request_timeout,
success: function( data ) {
if ( data && data.fragments ) {
@ -68,7 +68,25 @@ jQuery( function( $ ) {
/* Named callback for refreshing cart fragment */
function refresh_cart_fragment() {
$.ajax( $fragment_refresh );
const controller = new AbortController();
const timeoutId = setTimeout( () => controller.abort(), $fragment_refresh.timeout );
window.fetch( $fragment_refresh.url, {
method: $fragment_refresh.type,
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
body: $fragment_refresh.data,
signal: controller.signal
} )
.then( response => {
clearTimeout( timeoutId );
if ( !response.ok ) {
throw new Error( response.statusText );
}
return response.json();
} )
.then( $fragment_refresh.success )
.catch( error => $fragment_refresh.error() );
}
/* Cart Handling */

View File

@ -8,6 +8,27 @@ jQuery( function( $ ) {
// Utility functions for the file.
/**
* Perform an AJAX request that expects an HTML response.
*
* @param {Object} options
*/
const ajax = options => {
window.fetch( options.url, {
method: options.type || 'GET',
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
body: options.data
} )
.then( response => {
if ( !response.ok ) {
throw new Error( response.statusText );
}
return response.text();
} )
.then( options.success )
.finally( () => options.complete() );
};
/**
* Gets a url for a given AJAX endpoint.
*
@ -222,13 +243,17 @@ jQuery( function( $ ) {
var data = {
security: wc_cart_params.update_shipping_method_nonce,
shipping_method: shipping_methods
};
$.ajax( {
// Flatten shipping_methods for use in URLSearchParams()
for ( var k in shipping_methods ) {
data[ 'shipping_method[' + k + ']' ] = shipping_methods[ k ];
}
ajax( {
type: 'post',
url: get_url( 'update_shipping_method' ),
data: data,
data: new URLSearchParams( data ).toString(),
dataType: 'html',
success: function( response ) {
update_cart_totals_div( response );
@ -260,10 +285,10 @@ jQuery( function( $ ) {
.appendTo( $form );
// Make call to actual form post URL.
$.ajax( {
ajax( {
type: $form.attr( 'method' ),
url: $form.attr( 'action' ),
data: $form.serialize(),
data: new URLSearchParams( new FormData( $form[0] ) ).toString(),
dataType: 'html',
success: function( response ) {
update_wc_div( response );
@ -347,10 +372,10 @@ jQuery( function( $ ) {
block( $( 'div.cart_totals' ) );
// Make call to actual form post URL.
$.ajax( {
ajax( {
type: $form.attr( 'method' ),
url: $form.attr( 'action' ),
data: $form.serialize(),
data: new URLSearchParams( new FormData( $form[0] ) ).toString(),
dataType: 'html',
success: function( response ) {
update_wc_div( response, preserve_notices );
@ -369,7 +394,7 @@ jQuery( function( $ ) {
update_cart_totals: function() {
block( $( 'div.cart_totals' ) );
$.ajax( {
ajax( {
url: get_url( 'get_cart_totals' ),
dataType: 'html',
success: function( response ) {
@ -471,10 +496,10 @@ jQuery( function( $ ) {
coupon_code: coupon_code
};
$.ajax( {
ajax( {
type: 'POST',
url: get_url( 'apply_coupon' ),
data: data,
data: new URLSearchParams( data ).toString(),
dataType: 'html',
success: function( response ) {
$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
@ -508,10 +533,10 @@ jQuery( function( $ ) {
coupon: coupon
};
$.ajax( {
ajax( {
type: 'POST',
url: get_url( 'remove_coupon' ),
data: data,
data: new URLSearchParams( data ).toString(),
dataType: 'html',
success: function( response ) {
$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
@ -541,10 +566,10 @@ jQuery( function( $ ) {
.appendTo( $form );
// Make call to actual form post URL.
$.ajax( {
ajax( {
type: $form.attr( 'method' ),
url: $form.attr( 'action' ),
data: $form.serialize(),
data: new URLSearchParams( new FormData( $form[0] ) ).toString(),
dataType: 'html',
success: function( response ) {
update_wc_div( response );
@ -571,7 +596,7 @@ jQuery( function( $ ) {
block( $form );
block( $( 'div.cart_totals' ) );
$.ajax( {
ajax( {
type: 'GET',
url: $a.attr( 'href' ),
dataType: 'html',
@ -600,7 +625,7 @@ jQuery( function( $ ) {
block( $form );
block( $( 'div.cart_totals' ) );
$.ajax( {
ajax( {
type: 'GET',
url: $a.attr( 'href' ),
dataType: 'html',

View File

@ -8,6 +8,38 @@ jQuery( function( $ ) {
$.blockUI.defaults.overlayCSS.cursor = 'default';
const ajax = options => {
const controller = new AbortController();
window.fetch( options.url, {
method: options.type,
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
body: options.data,
signal: controller.signal
} )
.then( response => {
response.text().then( text => {
if ( !response.ok ) {
const error = new Error( response.statusText );
error.responseText = text; // Needed for when wc_checkout_params.debug_mode is enabled
throw error;
}
if ( options.dataType === 'html' ) {
options.success( text );
return;
}
const json = JSON.parse( ajax.dataFilter( text, 'json' ) );
options.success( json );
} );
} )
.catch( error => options.error && options.error( error.responseText, 'error', error.message ) );
return controller;
};
ajax.dataFilter = ( raw_response, dataType ) => raw_response;
var wc_checkout_form = {
updateTimer: false,
dirtyInput: false,
@ -256,11 +288,12 @@ jQuery( function( $ ) {
wc_checkout_form.updateTimer = setTimeout( wc_checkout_form.update_checkout_action, '5', args );
},
update_checkout_action: function( args ) {
if ( wc_checkout_form.xhr ) {
wc_checkout_form.xhr.abort();
if ( wc_checkout_form.controller ) {
wc_checkout_form.controller.abort();
}
if ( $( 'form.checkout' ).length === 0 ) {
var $form = $( 'form.checkout' );
if ( $form.length === 0 ) {
return;
}
@ -316,7 +349,7 @@ jQuery( function( $ ) {
s_address : s_address,
s_address_2 : s_address_2,
has_full_address: has_full_address,
post_data : $( 'form.checkout' ).serialize()
post_data : new URLSearchParams( new FormData( $form[0] ) ).toString()
};
if ( false !== args.update_shipping_method ) {
@ -327,7 +360,10 @@ jQuery( function( $ ) {
shipping_methods[ $( this ).data( 'index' ) ] = $( this ).val();
} );
data.shipping_method = shipping_methods;
// Flatten shipping_methods for use in URLSearchParams()
for ( var k in shipping_methods ) {
data[ 'shipping_method[' + k + ']' ] = shipping_methods[ k ];
}
}
$( '.woocommerce-checkout-payment, .woocommerce-checkout-review-order-table' ).block({
@ -338,10 +374,10 @@ jQuery( function( $ ) {
}
});
wc_checkout_form.xhr = $.ajax({
wc_checkout_form.controller = ajax({
type: 'POST',
url: wc_checkout_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'update_order_review' ),
data: data,
data: new URLSearchParams( data ).toString(),
success: function( data ) {
// Reload the page if requested
@ -404,8 +440,6 @@ jQuery( function( $ ) {
// Check for error
if ( data && 'failure' === data.result ) {
var $form = $( 'form.checkout' );
// Remove notices from all sources
$( '.woocommerce-error, .woocommerce-message' ).remove();
@ -486,39 +520,37 @@ jQuery( function( $ ) {
// Attach event to block reloading the page when the form has been submitted
wc_checkout_form.attachUnloadEventsOnSubmit();
// ajaxSetup is global, but we use it to ensure JSON is valid once returned.
$.ajaxSetup( {
dataFilter: function( raw_response, dataType ) {
// We only want to work with JSON
if ( 'json' !== dataType ) {
return raw_response;
}
if ( wc_checkout_form.is_valid_json( raw_response ) ) {
return raw_response;
} else {
// Attempt to fix the malformed JSON
var maybe_valid_json = raw_response.match( /{"result.*}/ );
if ( null === maybe_valid_json ) {
console.log( 'Unable to fix malformed JSON' );
} else if ( wc_checkout_form.is_valid_json( maybe_valid_json[0] ) ) {
console.log( 'Fixed malformed JSON. Original:' );
console.log( raw_response );
raw_response = maybe_valid_json[0];
} else {
console.log( 'Unable to fix malformed JSON' );
}
}
// ajax.dataFilter affects all ajax() calls, but we use it to ensure JSON is valid once returned.
ajax.dataFilter = function( raw_response, dataType ) {
// We only want to work with JSON
if ( 'json' !== dataType ) {
return raw_response;
}
} );
$.ajax({
if ( wc_checkout_form.is_valid_json( raw_response ) ) {
return raw_response;
} else {
// Attempt to fix the malformed JSON
var maybe_valid_json = raw_response.match( /{"result.*}/ );
if ( null === maybe_valid_json ) {
console.log( 'Unable to fix malformed JSON' );
} else if ( wc_checkout_form.is_valid_json( maybe_valid_json[0] ) ) {
console.log( 'Fixed malformed JSON. Original:' );
console.log( raw_response );
raw_response = maybe_valid_json[0];
} else {
console.log( 'Unable to fix malformed JSON' );
}
}
return raw_response;
};
ajax({
type: 'POST',
url: wc_checkout_params.checkout_url,
data: $form.serialize(),
data: new URLSearchParams( new FormData( $form[0] ) ).toString(),
dataType: 'json',
success: function( result ) {
// Detach the unload handler that prevents a reload / redirect
@ -556,7 +588,7 @@ jQuery( function( $ ) {
}
}
},
error: function( jqXHR, textStatus, errorThrown ) {
error: function( responseText, textStatus, errorThrown ) {
// Detach the unload handler that prevents a reload / redirect
wc_checkout_form.detachUnloadEventsOnSubmit();
@ -621,10 +653,10 @@ jQuery( function( $ ) {
coupon_code: $form.find( 'input[name="coupon_code"]' ).val()
};
$.ajax({
ajax({
type: 'POST',
url: wc_checkout_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'apply_coupon' ),
data: data,
data: new URLSearchParams( data ).toString(),
success: function( code ) {
$( '.woocommerce-error, .woocommerce-message' ).remove();
$form.removeClass( 'processing' ).unblock();
@ -661,10 +693,10 @@ jQuery( function( $ ) {
coupon: coupon
};
$.ajax({
ajax({
type: 'POST',
url: wc_checkout_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'remove_coupon' ),
data: data,
data: new URLSearchParams( data ).toString(),
success: function( code ) {
$( '.woocommerce-error, .woocommerce-message' ).remove();
container.removeClass( 'processing' ).unblock();
@ -679,10 +711,10 @@ jQuery( function( $ ) {
$( 'form.checkout_coupon' ).find( 'input[name="coupon_code"]' ).val( '' );
}
},
error: function ( jqXHR ) {
error: function ( responseText ) {
if ( wc_checkout_params.debug_mode ) {
/* jshint devel: true */
console.log( jqXHR.responseText );
console.log( responseText );
}
},
dataType: 'html'

View File

@ -127,7 +127,17 @@ jQuery( function( $ ) {
// Get the current geo hash. If it doesn't exist, or if it doesn't match the current
// page URL, perform a geolocation request.
if ( ! get_geo_hash() || needs_refresh() ) {
$.ajax( $geolocate_customer );
window.fetch( $geolocate_customer.url, {
method: $geolocate_customer.type,
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }
} )
.then( response => {
if ( !response.ok ) {
throw new Error( response.statusText );
}
return response.json();
} )
.then( $geolocate_customer.success );
}
// Page updates.