【问题标题】:Concurrency issue when updating Wordpress metadata via ajax通过 ajax 更新 Wordpress 元数据时的并发问题
【发布时间】:2012-10-31 00:46:26
【问题描述】:

场景如下:我正在构建一个 Wordpress 插件来管理我参与的一些调查研究。项目管理员能够从 WP 管理界面上传一个 csv 文件。在客户端,当文件上传时,它会遍历文件的每一行,提取有关用户的必要信息,然后进行 AJAX 调用以将参与者添加到项目中。我决定在客户端解析 csv 文件并一一提交 ajax 请求,以便在每次返回时更新进度条。 javascript看起来像这样:

$( '#csv_upload_button' ).click( function() {
    // declare the necessary variables
    var f = $( '#csv_file_input' )[0].files[0],
        fr = new FileReader,
        rows, headers, dialog, count, remaining;
    // when the file loads
    fr.onload = function() {
        // get the rows, the count, number remaining to process, and headers
        rows = fr.result.split( "\n" );
        remaining = count = rows.length - 1; // -1 to account for header row
        headers = $.trim( rows[0] ).split( ',' );
        // create the dialog box to show the progress bar
        dialog = $( '<div></div>' )
                    .html( 
                        '<p>Loading...</p>' +
                        '<p><progress id="csv_upload_progress" max="' + count + 
                        '" min="0" value="0"></p>' )
                    .dialog( { modal: true; } );
        // then for each row in the file
        $( rows ).each( function( i, r ) {
            // create an object to hold the data
            var data = {}, row = $.trim( r ).split( ',' ), j;
            if ( i > 0 ) { // data starts on the second row
                // map the data into our object
                for ( j = 0; j < headers.length; j++ ) {
                    data[ headers[ j ] ] = row[ j ];
                }
                // send it to the server
                $.post(
                    ajaxurl, 
                    { 
                        action: 'import_panel_member', 
                        data: data, 
                        postid: $( '#post_ID' ).val() 
                    }, 
                    function( result ) {
                        var prog = $( '#csv_upload_progress' );
                        prog.attr( 'value', prog.attr( 'value' ) + 1 );
                        if ( 0 == --remaining ) {
                            // stuff to do when everything has been loaded
                        }
                    }
                );
            }
        });
    };
    // read the csv file
    fr.readAsText( f );
});

PHP 看起来像这样:

function import_panel_member() {
    header( 'content-type: application/json' );
    // get the variables sent from the client
    $postid = $_POST[ 'postid' ];
    $data   = $_POST[ 'data'   ];
    /*
     * ...do other things involving talking to a 3rd party server...
     */
    // get the WP meta data variable to be updated
    $participants = get_post_meta( $postid, '_project_participants', true );
    // modify it
    $participants[] = $data;
    // update the database
    update_post_meta( $postid, '_project_participants', $participants );
    // return a message to the client
    echo json_encode( (object) array( 'success' => 1, 'message' => 'added' ) );
    exit;
}

问题在于,由于这些请求是异步发生的,_project_participants 元数据字段似乎仅由要处理的最后一条记录更新。换句话说,只有列表中的最后一个人会显示在参与者列表中。以下是我尝试过的一些事情:

  1. $.post() 更改为$.ajax() 并设置async: false
    这可行,但速度要慢得多(由于同步调用),并且由于某种原因,它会阻止我的对话框显示,直到所有 ajax 调用完成。
  2. 将整个 csv 文件上传到服务器并在那里处理
    而不是在客户端解析 csv。这也有效,但我认为我无法从服务器获得可用于更新进度条的中间反馈。此请求可能需要相当长的时间,我不希望用户在请求完成之前“放弃”该请求。这样做时,有时服务器永远不会响应 ajax 调用。

所以也许我很贪心,只是想要我的蛋糕并且也吃掉它。如何利用异步请求的速度,让我有机会通过进度条向用户提供反馈,但又不会因服务器上的并发问题而陷入困境?

【问题讨论】:

    标签: php jquery wordpress concurrency progress


    【解决方案1】:

    我想通了。答案是两种方法的混合。我可以使用一系列$.post() 调用来做在异步模式下效果更好的东西,然后上传整个 csv 来做在同步模式下效果更好的东西。如果没有在 SO 中输入完整的解释,永远不会明白这一点!

    【讨论】:

    • 您也可以一次上传整个内容并使用Transients API 来跟踪过程。然后客户端可以轮询服务器并根据缓存中的值返回处理状态。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-30
    • 2011-01-25
    • 2019-09-26
    • 1970-01-01
    • 1970-01-01
    • 2013-11-07
    相关资源
    最近更新 更多