在后台运行查询,等待它们完成,并在剩余的 JSL 脚本中引用它们问题
您希望在后台运行查询,以便用户界面不会冻结,或者您希望同时运行多个查询,然后合并结果。 有时,很难将您需要的所有功能放入后台查询的“运行时完成”脚本中。
解决方案
每个查询将结果保存在所有脚本都可以访问的新命名空间中(查询和原始脚本)。原始脚本在继续之前会不断检查结果。
//Example script which runs queries in the background and references their results
//once finished.
Names default to here(1);
// Namespace to share data between background query and this script
ns = new namespace( "queries" );
// Flags which the background query will set to 1 when the background query is complete
ns:query1isdone = 0;
ns:query2isdone = 0;
// Open a window to display results
win = New window("Query Status", show menu(0), show toolbars(0),
text box("Status of queries:"),
tb = tablebox( string col box( "Query" , { "Query 1", "Query 2" } ),
string col box( "Status", { "Not Started", "Not Started" } ) ),
tbStatus = text box("Starting queries.")
);
wait(0); //make sure window shows up
// Define and start background queries
// First Query
sql_query1 = New SQL Query(
Connection( "ODBC:DSN=Test Source;DATABASE=Test Database;" ),
QueryName( "Query" ),
Select( vars ),
From( table ),
Where( condition )
);
sql_query1 << Run Background( OnRunComplete(
Names default to here(1);<BR /> ns = namespace( "queries" );
ns:dt1 = queryResult;
ns:query1isdone = 1;
) );
// Second Query
sql_query2 = New SQL Query(
Connection( "ODBC:DSN=Test Source;DATABASE=Test Database;" ),
QueryName( "Query" ),
Select( vars ),
From( table ),
Where( condition )
);
sql_query2 << Run Background( OnRunComplete(
Names default to here(1);<BR /> ns = namespace( "queries" );
ns:dt2 = queryResult;
ns:query2isdone = 1;
) );
// Every second check if the query is done (timeout after 10 seconds)
i=0;
allqueriesdone = 0;
starttime = tick seconds();
while( ( i < 10 ) & allqueriesdone == 0 ,
i++;
wait(1);
if( ns:query1isdone == 1,
tb << delete row( 1 );
tb << insert row( 1, {"Query 1", "Complete"} );,
tb << delete row( 1 );
tb << insert row( 1, {"Query 1", "Still Running"} );
);
if( ns:query2isdone == 1,
tb << delete row( 2 );
tb << insert row( 2, {"Query 2", "Complete"} );,
tb << delete row( 2 );
tb << insert row( 2, {"Query 2", "Still Running"} );
);
if( (ns:query1isdone == 1 ) & (ns:query2isdone == 1 ), allqueriesdone = 1 ); //indicate that everything finished
tbStatus << Set Text( "Queries are running, " || format(tick seconds() - starttime, "Fixed Dec", 12, 1) || " seconds elapsed." );
win << bring window to front;
);
// Show an error if any queries didn't finish
if( allqueriesdone == 0,
tbStatus << Set Text("Error, a query didn't finish and is still running!"),
tbStatus << Set Text("Queries finished after " || format(tick seconds() - starttime, "Fixed Dec", 12, 1) || " seconds.");
//win << Close Window; //could close window here
);
// Now reference the data tables
show( ns:dt1 );
show( ns:dt2 );您希望在后台运行查询,但需要与结果进行交互。此方法允许在与结果交互之前完成多个后台查询。
公用事业回复:在后台运行查询,等待它们完成,并在剩余的 JSL 脚本中引用它们你好@马克代顿,
感谢您深入研究这一点,因为您指出了我刚刚更正的脚本的不足之处。 我在 OnRunComplete 脚本中没有将名称默认设置为此处(1),因此它没有完全按照我的计划工作。这是更新前后命名空间的描述我只是制成:
概述
注意命名空间“查询”是如何的已创建在父脚本中然后引用的在 OnRunComplete 脚本中。变量 ns 本身仅用于引用命名空间“queries”。例如,在新的脚本窗口中您可以运行:
Names default to here(1);
ns = New Namespace("queries");
ns:a = 1
第二个脚本窗口可以通过调用获取 a 的值:
Names default to here(1);
Show(Namespace("queries"):a);
但您无法轻松地在另一个窗口中访问 ns。 但是,您可以在另一个窗口中定义一个新变量,然后以类似的方式访问 a:
Names default to here(1);
nsreference = Namespace("queries");
Show(nsreference);
或者,为了使代码更易于阅读,您可以在两个窗口中使用相同的变量名称。变量本身是不同的,因为它们是在不同的命名空间中定义的,但它们引用相同的东西,因此您可以以相同的方式使用它们。
Names default to here(1);
ns = Namespace("queries");
Show(ns:a);
这就是上面示例脚本中变量的使用方式:在每个引用命名空间“queries”的命名空间中创建一个名为“ns”的变量,从而更容易在这些脚本之间共享值。
变更前- 如果不启动名称默认为此处的每个 OnRunComplete 脚本(1),这将如何工作:
查看更多...
变更后- 脚本现在如何工作
该脚本使用了四个命名空间:
- 父脚本窗口的here命名空间
- 第一个查询的 OnRunComplete 脚本的此处命名空间
- 第二个查询的 OnRunComplete 脚本的here命名空间
- 名为“queries”的命名空间,由父脚本和两个 OnRunComplete 脚本引用
父脚本中的变量 ns 在here命名空间中定义为参考查询命名空间,使用 New Namespace() 创建。这意味着只有脚本窗口可以访问 ns,但 JMP 实例中的其他任何内容都可以引用 ns 引用的查询命名空间中保存的任何内容。
OnRunComplete 脚本在新环境中打开,并且无权访问父脚本的此处命名空间。因此,在该脚本的 here 命名空间中定义了一个也称为 ns 的新变量,并将其设置为使用 Namespace() 引用“查询”命名空间。每个运行完成的脚本都会在其自己的此处命名空间中创建名为 ns 的自己的变量,但随后每个变量都将被设置为引用相同的“查询”命名空间。
回复:在后台运行查询,等待它们完成,并在剩余的 JSL 脚本中引用它们首先,感谢您提供这个脚本。 使用命名空间、编写 SQL 查询脚本、测试是否完成,提供状态反馈、管理结果;该脚本将大量教学内容打包到几行 JSL 中。大部分内容我都能听懂,但是我没有太多定义和使用命名空间的经验,所以我有一个问题:
在脚本的第二行中,纳秒是定义为:
ns = new namespace( "queries" );
那么看来纳秒在 Run Background() 语句中重新定义:
sql_query2 << Run Background( OnRunComplete(
ns = namespace( "queries" );
ns:dt2 = queryResult;
ns:query2isdone = 1;
) );
sql_query1 和 2 中的命名空间是否与脚本开头定义的命名空间相同(看起来必须如此),或者它是查询语句本地的命名空间,因为名称默认为此处(1)开头的声明? 为什么纳秒需要在 Run Background() 语句中定义吗?
再次感谢您提供了一段简单、清晰、漂亮的代码。
回复:在后台运行查询,等待它们完成,并在剩余的 JSL 脚本中引用它们尽管如此,还是有一些很好的代码可以在紧要关头参考。 
回复:在后台运行查询,等待它们完成,并在剩余的 JSL 脚本中引用它们你好@Byron_JMP ,
我同意,如果目标是检查交互式运行的查询的状态,那么用户应该只看查询生成器。此状态窗口旨在演示用户通过简单的 Web 搜索难以找到的查询的处理部分,例如在脚本完成后引用脚本中的结果。 老实说,我记得很难想出一个最小的例子。我确信那里有更好的用例......
回复:在后台运行查询,等待它们完成,并在剩余的 JSL 脚本中引用它们这听起来是一个非常有趣的项目想法。
我只是想指出,在查询生成器中,有一个进度选项卡,我可以在其中查看正在运行的查询数量及其进度。 也许这将是一种编写查询构建器平台脚本来显示此信息而不是尝试从头开始获取它的方法?