gpt4 book ai didi

javascript - 由 JS Promises 排序的 AJAX 调用似乎以正确的顺序运行,但数据库的输出表明并非如此

转载 作者:行者123 更新时间:2023-11-29 02:48:02 27 4
gpt4 key购买 nike

我在这里处理两个文件。 query.php 是我为处理这个特定网站的所有 MySQL 查询而编写的脚本。 query_test.js 是一系列 AJAX 调用来测试 query.phpquery_test.js,正如您将在下面看到的那样,使用 Promises 对一个又一个测试进行排序,因为我已经使测试相互依赖。通过写入控制台,AJAX 调用出现 以始终以正确的顺序完成。问题是输出不一致,个别测试的输出显然并不总是反射(reflect)之前测试的结果。由于个别测试似乎工作得很好,我坚信这是一个顺序问题。我只是想不通这是为什么以及如何发生的。

为清楚起见,测试如下:

  • 测试 1:检索整个表并显示
  • 测试 2:添加新行,然后再次检索并显示表格
  • 测试3:选择刚刚添加的行,显示结果
  • 测试 4:更新刚刚添加的行,检索并显示表格
  • 测试5:删除刚刚添加的行,检索并显示表格

在下面的示例输出中,请注意在测试 2 之后检索到的表并未反射(reflect)添加了行,并且测试 3 的查询未返回任何内容。直到测试 4 之前添加的行似乎才出现。每次执行都会产生不同的输出;有时完全正常,有时像上面那样真的错了。控制台输出总是 显示每个调用都按照它应该的顺序进行。这让我觉得后端出了问题,但我不知道那是什么。

query.php

<?php
/**
The purpose of this script is to query the database in a number of ways.
This script should be called via AJAX. See below for supported actions and
required parameters for each.

-------- ACTIONS ($_POST["action"])-----------

1. GET_TABLE: retrieve an entire table
- Parameters:
"table_name": [String] name of the table
- Returns: [JSON] the entire table

2. UPDATE_TABLE: update a row in a table
- Parameters:
"table_name": [String] name of the table
"queries": [array] a list of queries, like so: <column>[<relational_operator]<value> to find rows to update
"values": [array] key=>value pairs for each column to be updated.

3. SELECT_TABLE: select specified columns from specified rows
- Parameters:
"table_name": [String] name of the table
"queries": [array] a list of queries, like so: <column>[<relational_operator]<value>
"columns": (optional) [array] a list of column names to be returned. default value is '*', or all columns
- Returns: [JSON] the rows returned from the query

4. ADD_ROW: add a row to a table
- Parameters:
"table_name": [String] name of the table
"values": [array] key=>value pairs of columns names and corresponding values for the new row

5. REMOVE_ROW: remove a row or rows from a table
- Parameters:
"table_name": [String] name of the table
"queries": [array] a list of queries, like so: <column>[<relational_operator]<value>

**/

// Constants
// Actions
define("GET_TABLE", 100);
define("UPDATE_TABLE", 101);
define("SELECT_TABLE", 102);
define("ADD_ROW", 103);
define("REMOVE_ROW", 104);

$server = "localhost";
$username = "root";
$password = "password";
$db_name = "test";

$conn = new mysqli($server, $username, $password, $db_name);
if ($conn->connect_error) die("Connection failed: " . $conn->connect_error);

// Action must be set
checkPOST("action") or die("Error: POST variable 'action' must be setand not empty.");
$action = $_POST["action"];

// Table name must be given for all actions
checkPOST("table_name") or die("Error: POST variable 'table_name' must be set and not empty.");
$table = $_POST["table_name"];

// Generic error message
$param_err = "Error: ensure all required params are set and not empty.";

// See which action needs to be done
switch ($action) {
case GET_TABLE:
// Simply run the query
$q = "SELECT * FROM $table";
$result = $conn->query($q);
$result or die("Query '" . $q . "' failed: " . $conn->error);
if ($result->num_rows > 0) {
$output = array();
while ($row = $result->fetch_assoc()) {
$output[] = $row;
}
echo json_encode($output);
}
break;
case UPDATE_TABLE:
// Check for additional required params
(checkPOST("values") && checkPOST("queries"))
or die($param_err);
$values = $_POST["values"];
$queries = $_POST["queries"];

$q = "UPDATE $table";

// Add the values to be set to the query
$q .= " SET ";
addQuotesToStrings($values);
addItemsToQuery($q, $values, true);

// Add the WHERE clause at the end of the query
$q .= " WHERE ";
addItemsToQuery($q, $queries, false);

// Now ready to send off the query to the db and report success or failure
$conn->query($q) or die("Query '" . $q . "' failed: " . $conn->error);
echo "Successfully updated " . $conn->affected_rows . " rows.";

break;
case SELECT_TABLE:
// Check for additional required params
checkPOST("queries") or die($param_err);
$queries = $_POST["queries"];

$q = "SELECT ";

// Add columns if specified
if (checkPOST("columns")) {
$columns = $_POST["columns"];
addItemsToQuery($q, $columns, false);
}
else $q .= "* "; // No columns specified. Select all

// Add table name
$q .= "FROM $table ";

// Add queries
$q .= "WHERE ";
addItemsToQuery($q, $queries, false);

// Now, send off query
$result = $conn->query($q);
$result or die("Query '" . $q . "' failed: " . $conn->error);
if ($result->num_rows > 0) {
$output = array();
while ($row = $result->fetch_assoc()) {
$output[] = $row;
}
echo json_encode($output);
}

break;
case ADD_ROW:
// Check for POST var "values"
checkPOST("values") or die($param_err);
$values = $_POST["values"];

$q = "INSERT INTO $table";

// First, add column names
$q .= " (";
addItemsToQuery($q, array_keys($values), false);
$q .= ") ";

// Add the values
$q .= "VALUES (";
addQuotesToStrings($values);
addItemsToQuery($q, $values, false);
$q .= ")";

// Run the query
$conn->query($q) or die("Query '" . $q . "' failed: " . $conn->error);
echo "Query was successful.";

break;
case REMOVE_ROW:
// Check for queries
checkPOST("queries") or die($param_err);
$queries = $_POST["queries"];

$q = "DELETE FROM $table";

// Add queries
$q .= " WHERE ";
addItemsToQuery($q, $queries, false);

// Run query
$conn->query($q) or die("Query '" . $q . "' failed: " . $conn->error);
echo "Query affected " . $conn->affected_rows . " rows.";

break;
default:
die("Error: POST variable 'action' has an unknown value.");
}

/**
Adds items from an array to an SQL query string
Assumes a space is present before the last keyword of the existing query.

@param string &$q A reference to an SQL query string
@param array $items An array containing strings that need to be added to a query in a list format (e.g. item1,item2,item3)
$param boolean $pairs A boolean that indicated whether the items are key=>value pairs or not
**/
function addItemsToQuery(&$q, $items, $pairs) {
$first = true;
foreach ($items as $name => $item) {
if (!$first) $q .= ", ";
else $first = false;
$q .= $pairs ? $name . "=" . $item : $item;
}
}

/**
Adds single quotes to each string in a array of items for the purpose of being added to a MySQL query

@param array $values A reference to an array of items
**/
function addQuotesToStrings(&$values) {
foreach ($values as &$value) {
if (strcmp(gettype($value), "string") == 0) $value = "'" . $value . "'";
}
unset($value);
}

/**
Simple helper function to check if a POST var is set and not empty

@param string $name The name of the POST variable
**/
function checkPOST($name) {
return isset($_POST[$name]) && !empty($_POST[$name]);
}
?>


query_test.js

    // This script is a series of AJAX calls to test query.php

const GET_TABLE = 100;
const UPDATE_TABLE = 101;
const SELECT_TABLE = 102;
const ADD_ROW = 103;
const REMOVE_ROW = 104;

/**
Runs an AJAX request to query.php and displays the result

@param {jQuery} div A jQuery object div to place results
@param {array} params An assoc. array of POST variables for the AJAX call
@param {boolean} displayAsTable Determines where the result will be displayed as a table or as it is

@return {Promise} A Promise object
**/
function runTest(div, params, displayAsTable) {
return Promise.resolve($.post("../php/query.php", params, function(data) {
// Display result
if (displayAsTable) {
let tableData = JSON.parse(data);
let table = $('<table></table>');
for (let rowKey in tableData) {
let row = $('<tr></tr>');
for (let colKey in tableData[rowKey]) {
let col = $('<td></td>');
col.html(tableData[rowKey][colKey]);
row.append(col);
}
table.append(row);
}
div.append(table);
}
else div.append($('<p>' + data + '</p>'));
}));
}

var num = 0;
// Temporary function to test if Promise order holds up
function logOrder(test) {
num++;
console.log(test + " finished: " + num);
}

// ----------- Test 1: Retrieve table ----------------
let div = $('<div></div><br>');
let header = $('<h2>Test 1: Retrieve table</h2>');
div.append(header);
$('body').append(div);
let params = {action: GET_TABLE, table_name: "projects"};
var promise = runTest(div, params, true);

// ------------ Test 2: Add Row ----------------------
promise = promise.then(function(value) {
logOrder("Test 1");

let div = $('<div></div><br>');
let header = $('<h2>Test 2: Add Row</h2>');
div.append(header);
$('body').append(div);
let values = {title: "test_proj", pic: "none.jpg", brief: "testing", description: "this is a test"};
let params = {action: ADD_ROW, values: values, table_name: "projects"};
runTest(div, params, false);
}, function(error) {
alert(error);
});

// Get table to ensure row has been added
promise = promise.then(function(value) {
logOrder("Test 2");

let div = $('<div></div><br>');
$('body').append(div);
let params = {action: GET_TABLE, table_name: "projects"};
runTest(div, params, true);
}, function(error) {
alert(error);
});

// -------------- Test 3: Select table -------------------
promise = promise.then(function(value) {
logOrder("Test 2 Check");

let div = $('<div></div><br>');
let header = $('<h2>Test 3: Select Table</h2>');
div.append(header);
$('body').append(div);
let queries = ["title='test_proj'"];
let params = {action: SELECT_TABLE, table_name: "projects", queries: queries};
runTest(div, params, true);
}, function(error) {
alert(error);
});

// -------------- Test 4: Update table -------------------
promise = promise.then(function(value) {
logOrder("Test 3");

let div = $('<div></div><br>');
let header = $('<h2>Test 4: Update Table</h2>');
div.append(header);
$('body').append(div);
let queries = ["title='test_proj'"];
let values = {brief: "This was updated", description: "This was also updated"};
let params = {action: UPDATE_TABLE, table_name: "projects", queries: queries, values: values};
runTest(div, params, false);
}, function(error) {
alert(error);
});

// Get table to ensure table has been updated
promise = promise.then(function(value) {
logOrder("Test 4");

let div = $('<div></div><br>');
$('body').append(div);
let params = {action: GET_TABLE, table_name: "projects"};
runTest(div, params, true);
}, function(error) {
alert(error);
});

// -------------- Test 5: Remove Row(s) ------------------
promise = promise.then(function(value) {
logOrder("Test 4 Check");

let div = $('<div></div><br>');
let header = $('<h2>Test 5: Remove Row(s)</h2>');
div.append(header);
$('body').append(div);
let queries = ["title='test_proj'"];
let params = {action: REMOVE_ROW, table_name: "projects", queries: queries};
runTest(div, params, false);
}, function(error) {
alert(error);
});

// Get table to ensure row has been removed
promise = promise.then(function(value) {
logOrder("Test 5");

let div = $('<div></div>');
$('body').append(div);
let params = {action: GET_TABLE, table_name: "projects"};
runTest(div, params, true);
}, function(error) {
alert(error);
}).then(function(value) {
logOrder("Test 5 Check");
}, function(error) {
alert(error);
});


示例输出:

Test 1: Retrieve table

11 placeholder none.jpg placeholder placeholder description

Test 2: Add Row

Query was successful.

11 placeholder none.jpg placeholder placeholder description

Test 3: Select Table


Test 4: Update Table

Successfully updated 1 rows.

11 placeholder none.jpg placeholder placeholder description
17 test_proj none.jpg This was updated This was also updated

Test 5: Remove Row(s)

Query affected 1 rows.

11 placeholder none.jpg placeholder placeholder description

最佳答案

看了this 后我才知道我做错了什么.

我按照@DarkKnight 的建议进行了更改,但这不是问题,或者至少不是唯一的问题。

事实证明,我只需要在每个 promise.then() 成功函数中返回一个 promise。本来,我不是这样做的。因此,在第一次测试之后,每个后续测试都开始查询,然后调用下一个 then() 而不是等待结果,因为新的 promise 没有做任何事情。

这是新的 query_test.js:

// This script is a series of AJAX calls to test query.php

const GET_TABLE = 100;
const UPDATE_TABLE = 101;
const SELECT_TABLE = 102;
const ADD_ROW = 103;
const REMOVE_ROW = 104;

/**
Runs an AJAX request to query.php and displays the result

@param {jQuery} div A jQuery object div to place results
@param {array} params An assoc. array of POST variables for the AJAX call
@param {boolean} displayAsTable Determines where the result will be displayed as a table or as it is

@return {Promise} A Promise object
**/
function runTest(div, params, displayAsTable) {
return new Promise(function(resolve, reject) {
$.post("../php/query.php", params, function(data) {
// Display result
if (displayAsTable) {
let tableData = JSON.parse(data);
let table = $('<table></table>');
for (let rowKey in tableData) {
let row = $('<tr></tr>');
for (let colKey in tableData[rowKey]) {
let col = $('<td></td>');
col.html(tableData[rowKey][colKey]);
row.append(col);
}
table.append(row);
}
div.append(table);
}
else div.append($('<p>' + data + '</p>'));
}).then(resolve, reject)
});
}

var num = 0;
// Temporary function to test if Promise order holds up
function logOrder(test) {
num++;
console.log(test + " finished: " + num);
}

var promise = Promise.resolve();

// ----------- Test 1: Retrieve table ----------------
promise = promise.then(function(value) {
let div = $('<div></div><br>');
let header = $('<h2>Test 1: Retrieve table</h2>');
div.append(header);
$('body').append(div);
let params = {action: GET_TABLE, table_name: "projects"};
return runTest(div, params, true);
}, function(error) {
alert(error);
});

// ------------ Test 2: Add Row ----------------------
promise = promise.then(function(value) {
logOrder("Test 1");

let div = $('<div></div><br>');
let header = $('<h2>Test 2: Add Row</h2>');
div.append(header);
$('body').append(div);
let values = {title: "test_proj", pic: "none.jpg", brief: "testing", description: "this is a test"};
let params = {action: ADD_ROW, values: values, table_name: "projects"};
return runTest(div, params, false);
}, function(error) {
alert(error);
});

// Get table to ensure row has been added
promise = promise.then(function(value) {
logOrder("Test 2");

let div = $('<div></div><br>');
$('body').append(div);
let params = {action: GET_TABLE, table_name: "projects"};
return runTest(div, params, true);
}, function(error) {
alert(error);
});

// -------------- Test 3: Select table -------------------
promise = promise.then(function(value) {
logOrder("Test 2 Check");

let div = $('<div></div><br>');
let header = $('<h2>Test 3: Select Table</h2>');
div.append(header);
$('body').append(div);
let queries = ["title='test_proj'"];
let params = {action: SELECT_TABLE, table_name: "projects", queries: queries};
return runTest(div, params, true);
}, function(error) {
alert(error);
});

// -------------- Test 4: Update table -------------------
promise = promise.then(function(value) {
logOrder("Test 3");

let div = $('<div></div><br>');
let header = $('<h2>Test 4: Update Table</h2>');
div.append(header);
$('body').append(div);
let queries = ["title='test_proj'"];
let values = {brief: "This was updated", description: "This was also updated"};
let params = {action: UPDATE_TABLE, table_name: "projects", queries: queries, values: values};
return runTest(div, params, false);
}, function(error) {
alert(error);
});

// Get table to ensure table has been updated
promise = promise.then(function(value) {
logOrder("Test 4");

let div = $('<div></div><br>');
$('body').append(div);
let params = {action: GET_TABLE, table_name: "projects"};
return runTest(div, params, true);
}, function(error) {
alert(error);
});

// -------------- Test 5: Remove Row(s) ------------------
promise = promise.then(function(value) {
logOrder("Test 4 Check");

let div = $('<div></div><br>');
let header = $('<h2>Test 5: Remove Row(s)</h2>');
div.append(header);
$('body').append(div);
let queries = ["title='test_proj'"];
let params = {action: REMOVE_ROW, table_name: "projects", queries: queries};
return runTest(div, params, false);
}, function(error) {
alert(error);
});

// Get table to ensure row has been removed
promise = promise.then(function(value) {
logOrder("Test 5");

let div = $('<div></div>');
$('body').append(div);
let params = {action: GET_TABLE, table_name: "projects"};
return runTest(div, params, true);
}, function(error) {
alert(error);
});

promise.then(function(value) {
logOrder("Test 5 Check");
}, function(error) {
alert(error);
});

关于javascript - 由 JS Promises 排序的 AJAX 调用似乎以正确的顺序运行,但数据库的输出表明并非如此,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39459396/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com