Ваш тест не имеет ничего общего с производительностью между async/await
и сырыми обещаниями. Все, что я вижу, это то, что для вычисления ошибки требуется больше времени. Ожидается
. Вернуться к основному вопросу, следует использовать async/await
, а не .then
с необработанными обещаниями?
Имейте в виду, что async/await
- это просто синтаксический сахар над сырые обещания, поэтому не должно оказывать большого влияния на общую производительность. Тем не менее, это делает ваш код более линейным, что избавляет от когнитивных накладных расходов от разработчика.
Вывод - это то, что вы предпочитаете. Обещания могут быть polyfill'd, но новые синтаксисы не могут, поэтому вы можете иметь это в виду, когда решаете, какой стиль использовать.
Некоторое недоразумение:
Столбец ошибок, возвращенный из цепочки обещаний, не дает никакого представления о том, где произошла ошибка.
blockquote>Это неверно. Быстрая проверка:
function error() { return new Promise(function(res, rej) { res(undefined()); // uh oh }); } error().then(console.log, e => console.log("Uh oh!", e.stack));
показывает весь стек ошибок, включая местоположение.
PDO не очень хорош с такими вещами. Вам нужно создать строку с вопросительными знаками динамически и вставить в запрос.
$in = str_repeat('?,', count($in_array) - 1) . '?';
$sql = "SELECT * FROM my_table WHERE my_value IN ($in)";
$stm = $db->prepare($sql);
$stm->execute($in_array);
$data = $stm->fetchAll();
Если в запросе есть другие заполнители, вы можете использовать следующий подход (код берется из моего PDO tutorial ):
Вы можете использовать функцию array_merge()
, чтобы объединить все переменные в один массив, добавив другие переменные в виде массивов в том порядке, в каком они появляются в вашем query:
$arr = [1,2,3];
$in = str_repeat('?,', count($arr) - 1) . '?';
$sql = "SELECT * FROM table WHERE foo=? AND column IN ($in) AND bar=? AND baz=?";
$stm = $db->prepare($sql);
$params = array_merge([$foo], $arr, [$bar, $baz]);
$stm->execute($params);
$data = $stm->fetchAll();
Если вы используете именованные заполнители, код будет немного сложнее, так как вам нужно создать последовательность именных заполнителей, например :id0,:id1,:id2
. Таким образом, код будет выглядеть следующим образом:
// other parameters that are going into query
$params = ["foo" => "foo", "bar" => "bar"];
$ids = [1,2,3];
$in = "";
foreach ($ids as $i => $item)
{
$key = ":id".$i;
$in .= "$key,";
$in_params[$key] = $item; // collecting values into key-value array
}
$in = rtrim($in,","); // :id0,:id1,:id2
$sql = "SELECT * FROM table WHERE foo=:foo AND id IN ($in) AND bar=:bar";
$stm = $db->prepare($sql);
$stm->execute(array_merge($params,$in_params)); // just merge two arrays
$data = $stm->fetchAll();
К счастью, для названных заполнителей нам не обязательно следовать строгий порядок, поэтому мы можем объединить наши массивы в любом порядке.
Я только что столкнулся с этой проблемой и закодировал небольшую обертку. Это не самый красивый или лучший код, я уверен, но он может помочь кому-то, вот он:
function runQuery(PDO $PDO, string $sql, array $params = [])
{
if (!count($params)) {
return $PDO->query($sql);
}
foreach ($params as $key => $values) {
if (is_array($values)) {
// get placeholder from array, e.g. ids => [7,12,3] would be ':ids'
$oldPlaceholder = ':'.$key;
$newPlaceholders = '';
$newParams = [];
// loop through array to create new placeholders & new named parameters
for($i = 1; $i <= count($values); $i++) {
// this gives us :ids1, :ids2, :ids3 etc
$newKey = $oldPlaceholder.$i;
$newPlaceholders .= $newKey.', ';
// this builds an associative array of the new named parameters
$newParams[$newKey] = $values[$i - 1];
}
//trim off the trailing comma and space
$newPlaceholders = rtrim($newPlaceholders, ', ');
// remove the old parameter
unset($params[$key]);
// and replace with the new ones
$params = array_merge($params, $newParams);
// amend the query
$sql = str_replace($oldPlaceholder, $newPlaceholders, $sql);
}
}
$statement = $PDO->prepare($sql);
$statement->execute($params);
return $statement;
}
Например, передавая их в:
SELECT * FROM users WHERE userId IN (:ids)
array(1) {
["ids"]=>
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
}
Становится:
SELECT * FROM users WHERE userId IN (:ids1, :ids2, :ids3)
array(3) {
[":ids1"]=>
int(1)
[":ids2"]=>
int(2)
[":ids3"]=>
int(3)
}
Это не пуленепробиваемый, но, как единственный разработчик для моих потребностей, он отлично работает, пока все равно.
Поскольку PDO, похоже, не дает хорошего решения, вы можете также рассмотреть возможность использования DBAL, который в основном следует API PDO, но также добавляет некоторые полезные функции http://docs.doctrine-project.org/ project / doctrine-dbal / ru / latest / reference / data-retrieval-and-manipulation.html # list-of-parameters-conversion
$stmt = $conn->executeQuery('SELECT * FROM articles WHERE id IN (?)',
array(array(1, 2, 3, 4, 5, 6)),
array(\Doctrine\DBAL\Connection::PARAM_INT_ARRAY)
);
Возможно, есть и другие пакеты там, которые не добавляют сложности и не скрывают взаимодействия с базой данных (как и большинство ORM), но в то же время облегчают небольшие типичные задачи.
Подстановка переменных в подготовленных инструкциях PDO не поддерживает массивы. Это один на один.
Вы можете обойти эту проблему, создав необходимое количество заполнителей на основе длины массива.
$variables = array ('1', '2', '3');
$placeholders = str_repeat ('?, ', count ($variables) - 1) . '?';
$query = $pdo -> prepare ("SELECT * FROM table WHERE column IN($placeholders)");
if ($query -> execute ($variables)) {
// ...
}
Как я понимаю, это потому, что PDO будет рассматривать содержимое $ in_values как отдельный элемент и будет вполне соответствующим образом. PDO увидит 1,2,3 как одну строку, поэтому запрос будет выглядеть примерно как
SELECT * FROM table WHERE my_value IN ("1,2,3")
Вы может подумать, что изменение impode будет иметь кавычки и запятые, чтобы исправить это, но это не будет. PDO увидит цитаты и изменит, как она цитирует строку.
Что касается того, почему ваш запрос соответствует первому значению, у меня нет объяснений.