Answer the question
In order to leave comments, you need to log in
Why does the VK API method return an empty result during an asynchronous GET request?
Good day!
I am developing a small application on Yii2 to search for users in communities using the VK API. The selection takes a lot of time, so I initially show the user the results of a single message selection and run the script in the background using an asynchronous GET request.
But in the end I get an empty result.
The method responsible for generating an asynchronous request:
private function curlRequestAsync($url, $params, $type = 'POST')
{
if (is_array($params)) {
foreach ($params as $key => &$val) {
if (is_array($val)) $val = implode(',', $val);
$post_params[] = $key.'='.urlencode($val);
}
$post_string = implode('&', $post_params);
} else {
$post_string = $params;
}
$parts = parse_url($url);
$fp = fsockopen($parts['host'],
isset($parts['port'])?$parts['port']:80,
$errno, $errstr, 30);
// Data goes in the path for a GET request
if('GET' == $type) {
$parts['path'] .= (!empty($post_string)) ? '?' . $post_string . '&user_id=' . Yii::$app->user->identity->id : '';
}
$out = "$type ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ".((!empty($post_string)) ? strlen($post_string) : '1000')."\r\n";
$out.= "Connection: Close\r\n\r\n";
// Data goes in the request body for a POST request
if ('POST' == $type && isset($post_string)) {
$out.= $post_string;
}
fwrite($fp, $out);
var_dump($out);
fclose($fp);
}
$this->curlRequestAsync(Url::toRoute(['get-all-members'], true), http_build_query(Yii::$app->request->get()), 'GET');
public function actionGetAllMembers() {
set_time_limit(0);
ignore_user_abort(true);
$model = new SearchForm();
$groups = $model->getUserSubscriptionsNew();
...
}
public function getUserSubscriptionsNew() {
$vk = \Yii::$app->authClientCollection->getClient('vkontakte');
$groups = $vk->post('users.getSubscriptions', ['extended' => 1, 'fields' => 'members_count'])['response'];
return $groups;
}
Answer the question
In order to leave comments, you need to log in
Solved this problem. Maybe someone will come in handy. Of course, using the functionality of Yii2, but the general principle, I think, is the same everywhere.
We create an additional field in the user table to store the token. When authorizing the user through VK, we write the OAuthToken object there (respectively processed by the serialize function).
In the actionGetAllMembers action, add the following. the code:
$user_id = Yii::$app->request->get('user_id');
$model->refreshSocialToken($user_id);
public function refreshSocialToken($user_id) {
$vk = \Yii::$app->authClientCollection->getClient('vkontakte');
$user = Auth::findOne(['user_id' => $user_id]);
$vk->setAccessToken(unserialize($user->token));
return true;
}
I already wrote to you about background tasks. in another question (gearman). Why did you decide that your method is asynchronous?
There is another solution, if you are too lazy to deal with task queues, make a cron that will access the database once every 10 seconds, for example. Add the user's request to the database, let the cron pull it and get the data. The user at you in any case will wait.
There is another option, but again with queues. You add requests to the queue and return the result to the comet server on some channel, the user listens to this channel and as the tasks are solved, the data on the page will be updated.
I'll try it visually:
Пользователь -запрос-> Сервер
Сервер -Часть ответа сразу-> Пользователь
Сервер -Сложная часть->Можно в очередь, можно в консольное приложение
Обработка -Какая-то часть-> Комет сервер (канал)
Пользователь (слушает канал) <-Обновляет данные - Комет сервер
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question