如何使用提供的参数限制对范围的 ajax 调用?

我正在尝试根据存储的(数组)值“填充”表单中的选择:city_selector_vars。这个存储的值显示了正确的值(见下面的代码)。


我遍历这个数组并尝试获取已定义 stateCode 的城市 (get_states)。我将 stateCode 作为值传递给函数。


如果我在获得预期回报state_data.country_code之前登录。$.post如果我登录state_data.country_code进去$.post,它并不总是与传递的 country_code 相同。我认为这与范围有关,但我的知识不足以弄清楚。


/**

 * city_selector_vars

 * [

 *      'countryCode' => 'NL',

 *      'stateCode' => 'NL-FL',

 *      'cityName' => 'A name'

 * ]

 * [

 *      'countryCode' => 'BE',

 *      'stateCode' => 'BE-BR',

 *      'cityName' => 'Another name'

 * ]

 */

if ( true === Array.isArray(city_selector_vars) ) {

    for (i = 0; i < city_selector_vars.length; i++ ) {

        get_states(city_selector_vars[i].countryCode, (response)=> {

            // console.log(response);

        });

    }

}


function get_states(countryCode, callback) {

    const state_data = {

        action: 'get_states_call',

        country_code: countryCode

    };

    // console.log(state_data.country_code) shows correct country code

    $.post(ajaxurl, state_data, (response)=> {

        // here the wrong response first shows

        // state_data.country_code is not always the same as state_data.country_code

        callback(response);

    });

}

function get_states_call( $country_code = false ) {

    // $country_code = always false, even though it is passed

    if ( false == $country_code ) {

        if ( isset( $_POST[ 'country_code' ] ) ) {

            // here it sometimes picks up the incorrect value

            $country_code = $_POST[ 'country_code' ];

        }

    }

    // code removed, since depends on code above

    $items = [];

    echo json_encode( $items );

    die();

}

因为它只是有时会拾取错误的值,所以我认为它与范围有关,但我没有足够的知识来确定它。


小怪兽爱吃肉
浏览 84回答 2
2回答

慕容森

从您的代码看来,您正在实现一个查询Wordpress数据的函数。我不认为您的问题是可变范围之一-而是异步函数的问题。您向每个国家/地区发送一个AJAX请求 - 每个请求“单独”传送到服务器,由服务器处理,然后返回响应。没有任何东西可以确保响应的到达顺序与发出请求的顺序相同。考虑一下:const arr = []function getSingleItem(id) {&nbsp; fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)&nbsp; &nbsp; .then(response => response.json())&nbsp; &nbsp; .then(json => {&nbsp; &nbsp; &nbsp; console.log(json.id)&nbsp; &nbsp; })}function getAllItems() {&nbsp; for (let i = 1; i < 10; i++) {&nbsp; &nbsp; getSingleItem(i)&nbsp; }}getAllItems()您可以在控制台中看到,响应没有按照请求发送的顺序到达(json.id实际上是从 1 到的运行数字i- 它们应该按顺序排列)。您必须注意自己订购:const arr = []function getSingleItem(id) {&nbsp; return fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)&nbsp; &nbsp; .then(response => response.json())&nbsp; &nbsp; .then(json => {&nbsp; &nbsp; &nbsp; return json.id&nbsp; &nbsp; })}async function getAllItems() {&nbsp; for (let i = 1; i < 10; i++) {&nbsp; &nbsp; const r = await getSingleItem(i)&nbsp; &nbsp; arr.push(r)&nbsp; }&nbsp; console.log(arr)}getAllItems()通过在函数中设置一个async await,我可以确定响应按请求发出的顺序显示。(在等待的响应没有到达之前,await不会“让”for()循环更进一步——有点像同步代码。)在这种情况下,我使用该fetch()函数返回一个Promise对象 - 一个可以在我的其他函数中等待的对象。你的代码您的 Javascript 代码可以修改:/**&nbsp;* city_selector_vars&nbsp;* [&nbsp;*&nbsp; &nbsp; &nbsp; 'countryCode' => 'NL',&nbsp;*&nbsp; &nbsp; &nbsp; 'stateCode' => 'NL-FL',&nbsp;*&nbsp; &nbsp; &nbsp; 'cityName' => 'A name'&nbsp;* ]&nbsp;* [&nbsp;*&nbsp; &nbsp; &nbsp; 'countryCode' => 'BE',&nbsp;*&nbsp; &nbsp; &nbsp; 'stateCode' => 'BE-BR',&nbsp;*&nbsp; &nbsp; &nbsp; 'cityName' => 'Another name'&nbsp;* ]&nbsp;*/async function get_all_state(city_selector_vars) {&nbsp; if (true === Array.isArray(city_selector_vars)) {&nbsp; &nbsp; // preparing the response array&nbsp; &nbsp; const response_states = []&nbsp; &nbsp; for (i = 0; i < city_selector_vars.length; i++) {&nbsp; &nbsp; &nbsp; // try - catch to handle errors&nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; // await the response&nbsp; &nbsp; &nbsp; &nbsp; const d = await get_states(city_selector_vars[i].countryCode);&nbsp; &nbsp; &nbsp; &nbsp; // add response to the response array&nbsp; &nbsp; &nbsp; &nbsp; response_states.push(d)&nbsp; &nbsp; &nbsp; } catch (err) {&nbsp; &nbsp; &nbsp; &nbsp; // handle error&nbsp; &nbsp; &nbsp; &nbsp; console.log(err)&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; // return the array - in order!&nbsp; &nbsp; return response_states&nbsp; }}function get_states(countryCode, callback) {&nbsp; const state_data = {&nbsp; &nbsp; action: 'get_states_call',&nbsp; &nbsp; country_code: countryCode&nbsp; };&nbsp; // console.log(state_data.country_code) shows correct country code&nbsp; // returning a Promise object, so await works in the other function&nbsp; return new Promise((resolve, reject) => {&nbsp; &nbsp; $.post(ajaxurl, state_data, (response) => {&nbsp; &nbsp; &nbsp; // here the wrong response first shows&nbsp; &nbsp; &nbsp; // state_data.country_code is not always the same as state_data.country_code&nbsp; &nbsp; &nbsp; // resolving the Promise when the response arrives&nbsp; &nbsp; &nbsp; resolve(response)&nbsp; &nbsp; });&nbsp; })}在您修改过的代码Promise中,必须显式创建 a(记住 -fetch()返回 a Promise?),因此它可以由async-await处理。我认为该片段应该按原样工作,但如果不是,那么只需要一个小调试:)WordPress 注释如果您使用 Wordpress 发送JSON,建议使用该wp_send_json()功能。更多:https ://developer.wordpress.org/reference/functions/wp_send_json/

SMILET

至于admin_post_edit_load_states功能,我认为Promise.all是正确的方法:function admin_post_edit_load_states() {&nbsp; &nbsp; if (true === Array.isArray(city_selector_vars)) {&nbsp; &nbsp; &nbsp; &nbsp; // preparing the response array&nbsp; &nbsp; &nbsp; &nbsp; const response_states = []&nbsp; &nbsp; &nbsp; &nbsp; for (i = 0; i < city_selector_vars.length; i++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // try - catch to handle errors&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // await the response&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const d = get_states(city_selector_vars[i].countryCode);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // add response to the response array&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; response_states.push(d)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (err) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // handle error&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; console.log(response_states);&nbsp; &nbsp; &nbsp; &nbsp; Promise.all(response_states).then(function(jsonResults) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var instance_count = 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (i = 0; i < jsonResults.length; i++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var obj = JSON.parse(jsonResults[i]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var len = obj.length;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var $stateValues = '';&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var select_state = $('select[name*="row-' + instance_count + '"][name*="stateCode"]');&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var stored_state = city_selector_vars[instance_count].stateCode;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; select_state.fadeIn();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (j = 0; j < len; j++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $selected = '';&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var state = obj[j];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var current_state = state.country_code + '-' + state.state_code;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (current_state === stored_state) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $selected = ' selected="selected"';&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var selected = $selected;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $stateValues += '<option value="' + state.country_code + '-' + state.state_code + '"' + selected + '>' + state.state_name + '</option>';&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; select_state.append($stateValues);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; instance_count++;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; }}这应该在异步的同时保持原始顺序。注意我们在这里做什么:首先,我们response_states用 Promise 填充数组(每次调用 get_states 都会返回一个 Promise)。然后,Promise.all(response_states)创建一个新的 Promise,当 response_states 数组中的所有 Promise 都被解决时,该 Promise 将被解决。最后,参数 jsonResults 是一个数组,其中包含数组中每个已解析承诺的对应值response_states。让我们看看它是否有效。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript