等待一个异步函数return一个范围对象
Await a asynchronous function return a range object
我想用一个函数来return一个范围对象,但是因为这个函数是异步的,所以当我的代码到达currentRangeSelection.select();
时,它仍然是null
。如何强制代码等待函数 getCurrentRangeSelection
以便我可以获取对象而不是 undefined
?
编辑 1 - Rick Kirkham:我已经简化了代码,所以现在可以将它粘贴到默认 Basic API在ScriptLab中调用(JavaScript)模板进行测试。
在研究了几个小时的 Promises 之后,我认为我已经接近我想要的了,但它仍然不起作用:
$("#run").click(run);
function run() {
var currentRangeSelection;
return Excel.run(function (context) {
return context.sync()
.then(function () {
return getCurrentRangeSelection(currentRangeSelection)
})
.then(function () {
// this returns an error because currentRangeSelection is undefined:
console.log("Outside the function: " + currentRangeSelection.address);
currentRangeSelection.select();
return context.sync();
})
})
.catch(function (error) {
console.log(error);
});
}
function getCurrentRangeSelection(rangeSelection) {
return Excel.run(function (context) {
return context.sync()
.then(function () {
rangeSelection = context.workbook.getSelectedRange();
rangeSelection.load();
return context.sync();
})
.then(function () {
// this works:
console.log("Inside the function: " + rangeSelection.address);
return context.sync();
});
});
}
如您所见,现在函数 return 是 Promise
因为它(我认为)是 Excel.run
函数的 return 值,现在我通过所需的 return 范围作为参数,但仍然不起作用。
还有更多提示吗?
编辑 2 - Rick Kirkham
(1) 我试图创建一个 return 是 Promise 的函数,因此我可以将它插入到调用者 then
链中。因此,我唯一的选择是将 return 范围的参数作为参考传递。
(2) 是的,我同意你的看法。我认为 (1) 解释了为什么我首先没有 return 范围对象。
(3) 是的,我修复了。
(4) 原始功能更复杂,来自 Office-JS API 的单一方法不会 return 我真正想要的。我通过这样做解决了我的问题:
$("#run").click(run);
function run() {
var testRange;
return Excel.run(function (context) {
return context.sync()
.then(function () {
testRange = getCurrentRangeSelection(context);
testRange.load();
return context.sync();
})
.then(function () {
console.log(testRange.address); // this works
return context.sync();
});
}).catch(function (error) {
console.log(error);
});
}
function getCurrentRangeSelection(context) {
var rangeSelection = context.workbook.getSelectedRange();
var activeWorksheet = context.workbook.worksheets.getActiveWorksheet();
var usedRange = activeWorksheet.getUsedRange();
return usedRange.getIntersection(rangeSelection);
}
我的下一个问题你用你的编辑回答了:"What if I wanted the function getCurrentRangeSelection
to return an already loaded
object?"
感谢您提供示例和答案!
试试这个:将 getCurrentRangeSelection
函数重新设计为 return Promise 对象。然后调用promise对象的then
方法调用currentRangeSelection.select()
根据以下 OP 的评论进行编辑并重写问题:
请转到 this sample 并查看 home.js 文件中的 getDocumentFilePath
函数。像它一样构造您的 getCurrentRangeSelection
方法,并将上下文对象作为参数传递给它。然后使用上下文对象通过 context.workbook.getSelectedRange()
方法获取当前选择的范围。然后将你想要的东西传递给return(我认为是当前选择的范围)作为参数传递给resolve
方法。
我想用一个函数来return一个范围对象,但是因为这个函数是异步的,所以当我的代码到达currentRangeSelection.select();
时,它仍然是null
。如何强制代码等待函数 getCurrentRangeSelection
以便我可以获取对象而不是 undefined
?
编辑 1 - Rick Kirkham:我已经简化了代码,所以现在可以将它粘贴到默认 Basic API在ScriptLab中调用(JavaScript)模板进行测试。
在研究了几个小时的 Promises 之后,我认为我已经接近我想要的了,但它仍然不起作用:
$("#run").click(run);
function run() {
var currentRangeSelection;
return Excel.run(function (context) {
return context.sync()
.then(function () {
return getCurrentRangeSelection(currentRangeSelection)
})
.then(function () {
// this returns an error because currentRangeSelection is undefined:
console.log("Outside the function: " + currentRangeSelection.address);
currentRangeSelection.select();
return context.sync();
})
})
.catch(function (error) {
console.log(error);
});
}
function getCurrentRangeSelection(rangeSelection) {
return Excel.run(function (context) {
return context.sync()
.then(function () {
rangeSelection = context.workbook.getSelectedRange();
rangeSelection.load();
return context.sync();
})
.then(function () {
// this works:
console.log("Inside the function: " + rangeSelection.address);
return context.sync();
});
});
}
如您所见,现在函数 return 是 Promise
因为它(我认为)是 Excel.run
函数的 return 值,现在我通过所需的 return 范围作为参数,但仍然不起作用。
还有更多提示吗?
编辑 2 - Rick Kirkham
(1) 我试图创建一个 return 是 Promise 的函数,因此我可以将它插入到调用者 then
链中。因此,我唯一的选择是将 return 范围的参数作为参考传递。
(2) 是的,我同意你的看法。我认为 (1) 解释了为什么我首先没有 return 范围对象。
(3) 是的,我修复了。
(4) 原始功能更复杂,来自 Office-JS API 的单一方法不会 return 我真正想要的。我通过这样做解决了我的问题:
$("#run").click(run);
function run() {
var testRange;
return Excel.run(function (context) {
return context.sync()
.then(function () {
testRange = getCurrentRangeSelection(context);
testRange.load();
return context.sync();
})
.then(function () {
console.log(testRange.address); // this works
return context.sync();
});
}).catch(function (error) {
console.log(error);
});
}
function getCurrentRangeSelection(context) {
var rangeSelection = context.workbook.getSelectedRange();
var activeWorksheet = context.workbook.worksheets.getActiveWorksheet();
var usedRange = activeWorksheet.getUsedRange();
return usedRange.getIntersection(rangeSelection);
}
我的下一个问题你用你的编辑回答了:"What if I wanted the function getCurrentRangeSelection
to return an already loaded
object?"
感谢您提供示例和答案!
试试这个:将 getCurrentRangeSelection
函数重新设计为 return Promise 对象。然后调用promise对象的then
方法调用currentRangeSelection.select()
根据以下 OP 的评论进行编辑并重写问题:
请转到 this sample 并查看 home.js 文件中的 getDocumentFilePath
函数。像它一样构造您的 getCurrentRangeSelection
方法,并将上下文对象作为参数传递给它。然后使用上下文对象通过 context.workbook.getSelectedRange()
方法获取当前选择的范围。然后将你想要的东西传递给return(我认为是当前选择的范围)作为参数传递给resolve
方法。