等待一个异步函数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方法。