首页 > 解决方案 > 试图理解 VSCode API 中的 Thennables。这些是等效的打字稿代码片段吗?

问题描述

我想在 VSCode API 中对文档执行一系列编辑。实现这一切的函数是Workspace.applyEdit,它返回一个Thennable. 这是我第一次使用这些函数,而这个函数返回的函数并不像我预期的那样工作。

片段1:

import { window, workspace, WorkspaceEdit, Position } from 'vscode';

//doesn't work, only makes first insertion, althouh all info text prints
export function applyEditReprex() {
    let text = "\ntest\n";
    let target = window.activeTextEditor.document.uri;
    let positions = [
        new Position(10, 1),
        new Position(15, 1),
        new Position(20, 1)
    ];
    positions.reduce((applyThennable, position) => {
        return (
            applyThennable.then(() => {
                console.info("Making new edit");
                let edit = new WorkspaceEdit();
                edit.insert(target, position, text);
                workspace.applyEdit(edit);
            }))
    },
        Promise.resolve()
    ).then(() => {
        console.info("Finished edits.");
    })
}

在第 12 行的目标文档中只出现了一个“test”实例。日志报告:

Making new edit
Making new edit
Making new edit
Finished edits.

片段 2:

我尝试将上面展开为直链调用:

import { window, workspace, WorkspaceEdit, Position } from 'vscode';

export function applyEditReprex2() {
    let text = "\ntest\n";
    let target = window.activeTextEditor.document.uri;
    let positions = [
        new Position(10, 1),
        new Position(15, 1),
        new Position(20, 1)
    ];
    console.info("Making new edit");
    let edit = new WorkspaceEdit();
    edit.insert(target, positions[0], text);
    workspace.applyEdit(edit).then(() => {
        console.info("Making new edit");
        let edit = new WorkspaceEdit();
        edit.insert(target, positions[1], text);
        workspace.applyEdit(edit).then(() => {
            console.info("Making new edit");
            let edit = new WorkspaceEdit();
            edit.insert(target, positions[2], text);
            workspace.applyEdit(edit).then(() => {
                console.info("Finished edits.");
            })
        })
    })
}

“test”的 3 个实例出现在目标文件的第 12、17、22 行。

日志报告:

Making new edit
Making new edit
Making new edit
Finished edits.

问题

是否有任何reduce我可能不知道的复杂或粗箭头函数可能导致第一个片段的行为与展开版本不同?或者另一种方式:展开的版本reduce在某些重要的方面不等同于?

标签: javascripttypescriptasynchronouspromisevscode-extensions

解决方案


您忘记了承诺回调中return的 thenable 对象,这对于承诺链接至关重要.then()

positions.reduce((prevPromise, position) => {
    return prevPromise.then(() => {
        console.info("Making new edit");
        const edit = new WorkspaceEdit();
        edit.insert(target, position, text);
        const applyThenable = workspace.applyEdit(edit);
        return applyThenable;
//      ^^^^^^^^^^^^^^^^^^^^
    });
}, Promise.resolve())

顺便说一句,我从您链接的文档中对 API 的理解是,您应该只制作一个WorkspaceEdit带有多个插入的 API:

const positions = [
    new Position(10, 1),
    new Position(15, 1),
    new Position(20, 1)
];
const edit = new WorkspaceEdit();
for (const position in positions) {
    edit.insert(target, position, text);
}
workspace.applyEdit(edit).then(() => {
    console.info("Finished multi-edit.");
})

推荐阅读