我有一个代码如下:
1 sub do_leave {
2
3 my ($asterisk, $event) = @_;
4 my $join_id;
5 my $id = $astman->send_action({ Action => 'Getvar',
6 Variable => 'join_id',
7 Channel => $event->{'Channel'},
8 }, \&get_value, undef, \$join_id);
9
10 sleep(2);
11 say "join_id is: $join_id";
12
13 my $sql = "UPDATE conference_log SET duration=(TIMESTAMPDIFF(SECOND, (SELECT start_conf), NOW())), end_conf=(NOW()) WHERE id=?";
14 my $sth = $dbh->prepare($sql);
15 $sth->execute($join_id);
16 }
17
18 sub get_value {
19 my ($ast, $resp, $ref_join_id) = @_;
20 for my $key (keys %$resp) {
21 if ($key eq "PARSED") {
22 $$ref_join_id = $resp->{$key}{"Value"};
23 }
24 }
25 }
我正在使用Asterisk::AMI模块从星号AMI获取信息。
只要有人离开会议,就会调用do_leave
子。我的问题是在get_value
中的所有语句之后执行do_leave
回调。
如何在第10行之前执行get_value
回调。\$join_id
中的变量send_action
是回调的第三个参数。我在sql语句之前需要$join_id
变量。
答案 0 :(得分:2)
对脚本进行最少的更改
sub do_leave {
my ($asterisk, $event) = @_;
my $join_id;
my $sub = sub {
get_value(@_);
say "join_id is: $join_id";
my $sql = "UPDATE conference_log SET duration=(TIMESTAMPDIFF(SECOND, (SELECT start_conf), NOW())), end_conf=(NOW()) WHERE id=?";
my $sth = $dbh->prepare($sql);
$sth->execute($join_id);
};
my $id = $astman->send_action({ Action => 'Getvar',
Variable => 'join_id',
Channel => $event->{'Channel'},
}, $sub, undef, \$join_id);
# sleep(2);
}
答案 1 :(得分:1)
我没有使用Asterisk :: AMI,但我认为send_action方法采用回调方法的原因是结果是异步返回的。你不能保证需要多长时间。
快速简便的解决方案是将数据库更新放在回调函数中,如下所示:
sub do_leave {
my ($asterisk, $event) = @_;
my $get_value = sub {
my ($ast, $resp, $ref_join_id) = @_;
for my $key (keys %$resp) {
if ($key eq "PARSED") {
my $ref_join_id = $resp->{$key}{"Value"};
my $sql = "UPDATE conference_log SET duration=(TIMESTAMPDIFF(SECOND, (SELECT start_conf), NOW())), end_conf=(NOW()) WHERE id=?";
my $sth = $dbh->prepare($sql);
$sth->execute($join_id);
}
}
};
my $id = $astman->send_action({ Action => 'Getvar',
Variable => 'join_id',
Channel => $event->{'Channel'},
}, $get_value);
}
请注意,我使用了一个匿名子,分配给一个变量,它允许你在外部do_leave子和回调子之间共享变量(这称为闭包)。但是在这种情况下可能不需要,因为没有共享变量。