为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

小怪兽爱吃肉 2022-07-15 10:10:17
我正在尝试根据存储的(数组)值“填充”表单中的选择: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();}因为它只是有时会拾取错误的值,所以我认为它与范围有关,但我没有足够的知识来确定它。
查看完整描述

2 回答

?
慕容森

TA贡献1853条经验 获得超18个赞

从您的代码看来,您正在实现一个查询Wordpress数据的函数。


我不认为您的问题是可变范围之一-而是异步函数的问题。您向每个国家/地区发送一个AJAX请求 - 每个请求“单独”传送到服务器,由服务器处理,然后返回响应。没有任何东西可以确保响应的到达顺序与发出请求的顺序相同。


考虑一下:


const arr = []


function getSingleItem(id) {

  fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)

    .then(response => response.json())

    .then(json => {

      console.log(json.id)

    })

}


function getAllItems() {

  for (let i = 1; i < 10; i++) {

    getSingleItem(i)

  }

}


getAllItems()


您可以在控制台中看到,响应没有按照请求发送的顺序到达(json.id实际上是从 1 到的运行数字i- 它们应该按顺序排列)。


您必须注意自己订购:


const arr = []


function getSingleItem(id) {

  return fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)

    .then(response => response.json())

    .then(json => {

      return json.id

    })

}


async function getAllItems() {

  for (let i = 1; i < 10; i++) {

    const r = await getSingleItem(i)

    arr.push(r)

  }

  console.log(arr)

}


getAllItems()


通过在函数中设置一个async await,我可以确定响应按请求发出的顺序显示。(在等待的响应没有到达之前,await不会“让”for()循环更进一步——有点像同步代码。)


在这种情况下,我使用该fetch()函数返回一个Promise对象 - 一个可以在我的其他函数中等待的对象。

你的代码

您的 Javascript 代码可以修改:


/**

 * city_selector_vars

 * [

 *      'countryCode' => 'NL',

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

 *      'cityName' => 'A name'

 * ]

 * [

 *      'countryCode' => 'BE',

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

 *      'cityName' => 'Another name'

 * ]

 */

async function get_all_state(city_selector_vars) {

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

    // preparing the response array

    const response_states = []

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

      // try - catch to handle errors

      try {

        // await the response

        const d = await get_states(city_selector_vars[i].countryCode);

        // add response to the response array

        response_states.push(d)

      } catch (err) {

        // handle error

        console.log(err)

      }

    }

    // return the array - in order!

    return response_states

  }

}


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


  // returning a Promise object, so await works in the other function

  return new Promise((resolve, reject) => {

    $.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

      // resolving the Promise when the response arrives

      resolve(response)

    });

  })



}


在您修改过的代码Promise中,必须显式创建 a(记住 -fetch()返回 a Promise?),因此它可以由async-await处理。


我认为该片段应该按原样工作,但如果不是,那么只需要一个小调试:)


WordPress 注释

如果您使用 Wordpress 发送JSON,建议使用该wp_send_json()功能。


更多:https ://developer.wordpress.org/reference/functions/wp_send_json/


查看完整回答
反对 回复 2022-07-15
?
SMILET

TA贡献1796条经验 获得超4个赞

至于admin_post_edit_load_states功能,我认为Promise.all是正确的方法:


function admin_post_edit_load_states() {

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

        // preparing the response array

        const response_states = []

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

            // try - catch to handle errors

            try {

                // await the response

                const d = get_states(city_selector_vars[i].countryCode);

                // add response to the response array

                response_states.push(d)

            } catch (err) {

                // handle error

                console.log(err)

            }

        }

        console.log(response_states);


        Promise.all(response_states).then(function(jsonResults) {

            var instance_count = 0;

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

                var obj = JSON.parse(jsonResults[i]);

                var len = obj.length;

                var $stateValues = '';

                var select_state = $('select[name*="row-' + instance_count + '"][name*="stateCode"]');

                var stored_state = city_selector_vars[instance_count].stateCode;

                select_state.fadeIn();

                for (j = 0; j < len; j++) {

                    $selected = '';

                    var state = obj[j];

                    var current_state = state.country_code + '-' + state.state_code;

                    if (current_state === stored_state) {

                        $selected = ' selected="selected"';

                    }

                    var selected = $selected;

                    $stateValues += '<option value="' + state.country_code + '-' + state.state_code + '"' + selected + '>' + state.state_name + '</option>';

                }

                select_state.append($stateValues);

                instance_count++;

            }

        });

    }

}

这应该在异步的同时保持原始顺序。注意我们在这里做什么:


首先,我们response_states用 Promise 填充数组(每次调用 get_states 都会返回一个 Promise)。然后,Promise.all(response_states)创建一个新的 Promise,当 response_states 数组中的所有 Promise 都被解决时,该 Promise 将被解决。最后,参数 jsonResults 是一个数组,其中包含数组中每个已解析承诺的对应值response_states。


让我们看看它是否有效。


查看完整回答
反对 回复 2022-07-15
  • 2 回答
  • 0 关注
  • 82 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信