JavaScript Promise 回调在 Promise 本身之前执行
The JavaScript Promise callback is executed before the Promise itself
目前我正在做一个Oracle APEX页面,里面有放置文档参数的表单。我的目标是改进机制,根据数据库中的某些信息定义表单的哪些字段可供用户使用,哪些字段不可用。
我制作了 PL/SQL 过程并编写了 JavaScript 函数(以及 AJAX 过程)来帮助我解决这个任务,但是当我需要在定义可编辑的字段后执行一些JavaScript代码(例如,有时需要刷新一些与表单绑定的报表或从HTML页面中删除一些辅助元素).换句话说,我有函数enableFields(在参数页面加载时执行),它必须执行enableFieldsBase,然后回调函数callbackFunc 定义在输入参数中,但经过一些测试我发现后者执行 before 前者尽管使用 JavaScript承诺。
这里是 JavaScript 函数,它使用数据库中的信息使表单字段可用(或不可用):
function enableFieldsBase(){
var page = 'P' + $v('pFlowStepId') + '_'; //define the page
var docID = $v(page + 'DOC_ID'); //define the document
//get the information which fields are available and which are not
$.post('wwv_flow.show',
{'p_request' : 'APPLICATION_PROCESS=DOC_ENABLE_FIELDS',
'p_flow_id' : $v('pFlowId'),
'p_flow_step_id' : $v('pFlowStepId'),
'p_instance' : $v('pInstance'),
'x01' : docID},
function(pData) {
var res = eval('(' + pData+ ')');
if (res.status == "OK") {
//get the array of objects containing the shortened element names and the availability sign
var props = res.data;
//open or close the elements for edit
for (var i = 0; i < props.length; i++){
if (props[i].enabled == 1) apex.item(page + props[i].prop).enable();
else apex.item(page + props[i].prop).disable();
}
} else {
//…the code for catching the exceptions…
}
});
}
而这个就是JavaScript函数,它不仅执行了前面那个,还兼顾了回调函数:
function enableFields(callbackFunc){
var page = 'P' + $v('pFlowStepId') + '_';
//check if the variable callbackFunc is really a function
if (callbackFunc != undefined && typeof(callbackFunc) != 'function'){
//…the code for catching the exceptions…
}
if (callbackFunc != undefined){
var promise1 = new Promise(function(resolve,reject){
enableFieldsBase();
return resolve(true);
});
$.when(promise1).done(function(){
callbackFunc();
});
} else {
enableFieldsBase();
}
}
所以,我的问题如下:我做错了什么?是否可以不将回调函数显式放入enableFieldsBase的代码中?
我使用 Oracle 11g 和 Oracle APEX 4.2.6.00.03。
问题是您同步调用了 resolve
,没有等待 post 请求完成。所以承诺立即解决。
相反,您应该使用 $.post
return 开箱即用的承诺:
function enableFieldsBase(){
var page = 'P' + $v('pFlowStepId') + '_'; //define the page
var docID = $v(page + 'DOC_ID'); //define the document
//make sure to RETURN the result of the `$.post` call, and chain a `then` method call
return $.post('wwv_flow.show',
{'p_request' : 'APPLICATION_PROCESS=DOC_ENABLE_FIELDS',
'p_flow_id' : $v('pFlowId'),
'p_flow_step_id' : $v('pFlowStepId'),
'p_instance' : $v('pInstance'),
'x01' : docID}).then(function(pData) { // Use the `then` method
var res = eval('(' + pData+ ')');
if (res.status == "OK") {
//get the array of objects containing the shortened element names and the availability sign
var props = res.data;
//open or close the elements for edit
for (var i = 0; i < props.length; i++){
if (props[i].enabled == 1) apex.item(page + props[i].prop).enable();
else apex.item(page + props[i].prop).disable();
}
} else {
//…the code for catching the exceptions…
}
});
}
调用代码中:
if (callbackFunc != undefined){
enableFieldsBase().then(callbackFunc);
} else {
enableFieldsBase();
}
正如 jonrsharpe 在下面的评论中指出的那样,如果您向 then
传递一个不可调用的参数(如 undefined
),就好像您根本没有传递回调。所以可以进一步简化为:
enableFieldsBase().then(callbackFunc);
最好将 callbackFunc
参数删除为 enableFields
,而仅 return 承诺。 enableFields
的调用者应该自己决定是否要将 then
调用链接到它(或使用 await
)。
目前我正在做一个Oracle APEX页面,里面有放置文档参数的表单。我的目标是改进机制,根据数据库中的某些信息定义表单的哪些字段可供用户使用,哪些字段不可用。
我制作了 PL/SQL 过程并编写了 JavaScript 函数(以及 AJAX 过程)来帮助我解决这个任务,但是当我需要在定义可编辑的字段后执行一些JavaScript代码(例如,有时需要刷新一些与表单绑定的报表或从HTML页面中删除一些辅助元素).换句话说,我有函数enableFields(在参数页面加载时执行),它必须执行enableFieldsBase,然后回调函数callbackFunc 定义在输入参数中,但经过一些测试我发现后者执行 before 前者尽管使用 JavaScript承诺。
这里是 JavaScript 函数,它使用数据库中的信息使表单字段可用(或不可用):
function enableFieldsBase(){
var page = 'P' + $v('pFlowStepId') + '_'; //define the page
var docID = $v(page + 'DOC_ID'); //define the document
//get the information which fields are available and which are not
$.post('wwv_flow.show',
{'p_request' : 'APPLICATION_PROCESS=DOC_ENABLE_FIELDS',
'p_flow_id' : $v('pFlowId'),
'p_flow_step_id' : $v('pFlowStepId'),
'p_instance' : $v('pInstance'),
'x01' : docID},
function(pData) {
var res = eval('(' + pData+ ')');
if (res.status == "OK") {
//get the array of objects containing the shortened element names and the availability sign
var props = res.data;
//open or close the elements for edit
for (var i = 0; i < props.length; i++){
if (props[i].enabled == 1) apex.item(page + props[i].prop).enable();
else apex.item(page + props[i].prop).disable();
}
} else {
//…the code for catching the exceptions…
}
});
}
而这个就是JavaScript函数,它不仅执行了前面那个,还兼顾了回调函数:
function enableFields(callbackFunc){
var page = 'P' + $v('pFlowStepId') + '_';
//check if the variable callbackFunc is really a function
if (callbackFunc != undefined && typeof(callbackFunc) != 'function'){
//…the code for catching the exceptions…
}
if (callbackFunc != undefined){
var promise1 = new Promise(function(resolve,reject){
enableFieldsBase();
return resolve(true);
});
$.when(promise1).done(function(){
callbackFunc();
});
} else {
enableFieldsBase();
}
}
所以,我的问题如下:我做错了什么?是否可以不将回调函数显式放入enableFieldsBase的代码中?
我使用 Oracle 11g 和 Oracle APEX 4.2.6.00.03。
问题是您同步调用了 resolve
,没有等待 post 请求完成。所以承诺立即解决。
相反,您应该使用 $.post
return 开箱即用的承诺:
function enableFieldsBase(){
var page = 'P' + $v('pFlowStepId') + '_'; //define the page
var docID = $v(page + 'DOC_ID'); //define the document
//make sure to RETURN the result of the `$.post` call, and chain a `then` method call
return $.post('wwv_flow.show',
{'p_request' : 'APPLICATION_PROCESS=DOC_ENABLE_FIELDS',
'p_flow_id' : $v('pFlowId'),
'p_flow_step_id' : $v('pFlowStepId'),
'p_instance' : $v('pInstance'),
'x01' : docID}).then(function(pData) { // Use the `then` method
var res = eval('(' + pData+ ')');
if (res.status == "OK") {
//get the array of objects containing the shortened element names and the availability sign
var props = res.data;
//open or close the elements for edit
for (var i = 0; i < props.length; i++){
if (props[i].enabled == 1) apex.item(page + props[i].prop).enable();
else apex.item(page + props[i].prop).disable();
}
} else {
//…the code for catching the exceptions…
}
});
}
调用代码中:
if (callbackFunc != undefined){
enableFieldsBase().then(callbackFunc);
} else {
enableFieldsBase();
}
正如 jonrsharpe 在下面的评论中指出的那样,如果您向 then
传递一个不可调用的参数(如 undefined
),就好像您根本没有传递回调。所以可以进一步简化为:
enableFieldsBase().then(callbackFunc);
最好将 callbackFunc
参数删除为 enableFields
,而仅 return 承诺。 enableFields
的调用者应该自己决定是否要将 then
调用链接到它(或使用 await
)。