如何在承诺中从事件处理程序返回值

How to return values from an event handler in a promise?

本文关键字:事件处理 程序 返回值 承诺      更新时间:2023-09-26

我正在构建一个使用nodegit npm包的nodeJS应用程序。所以基于他们文档中的例子,我有了下面的章节。它使用了一个承诺链,看起来像一个JQuery事件处理程序。下面是我的函数:

export function prepareDiffs() {
    var patt = new RegExp('[0-9].[0-9]');
    var results: Array<Commit> = [];
    Git.Repository.open("features/tutorial") // Open the repository directory.
        .then(function (repo) { // Open the master branch.
            return repo.getMasterCommit();
        })
        .then(function (firstCommitOnMaster) { // Display information about commits on master.
            var history = firstCommitOnMaster.history(); // Create a new history event emitter.
            history.on("commit", function (commit) { // Listen for commit events from the history.
                var entry = new Commit();
                entry.hash = commit.sha();
                var step = patt.exec(commit.message());
                if (step !== null) {
                    entry.step = step.toString();
                }
                results.push(entry);
            })
            history.start(); // Start emitting events.
            console.log("return");
        });
}

因此,在history.on()事件处理程序中放入console.log显示了我想要看到的所有信息。所以我对我的数组推送很有信心。那么我如何才能让prepareDiffs()函数返回填充的results数组,或者至少是一个解析到数组的承诺?

注:我使用Typescript瞄准es6,所以async/await是可用的。

让您的第二个then回调创建并返回一个承诺,然后侦听end事件并在该点用您的数组解决承诺,参见***注释:

export function prepareDiffs() {
    var patt = new RegExp('[0-9].[0-9]');
    var results: Array<Commit> = [];
    // *** Note we're returning the result of the promise chain
    return Git.Repository.open("features/tutorial") // Open the repository directory.
        .then(function (repo) { // Open the master branch.
            return repo.getMasterCommit();
        })
        .then(function (firstCommitOnMaster) { // Display information about commits on master.
            // *** Create and return a promise
            return new Promise(function(resolve, reject) {
                var history = firstCommitOnMaster.history(); // Create a new history event emitter.
                history
                    .on("commit", function (commit) { // Listen for commit events from the history.
                        var entry = new Commit();
                        entry.hash = commit.sha();
                        var step = patt.exec(commit.message());
                        if (step !== null) {
                            entry.step = step.toString();
                        }
                        results.push(entry);
                    })
                    .on("end", function() { // *** Listen for the end
                        // *** Resolve the promise
                        resolve(results);
                    });
                history.start(); // Start emitting events.
                console.log("return");
            });
        });
}
我想强调的是,大多数情况下,当你已经在处理基于承诺的API时,你不想创建新的承诺。但是在这种情况下,因为你从事件发射器history()返回的事件中获得一系列异步commit事件,你不能直接使用承诺链,所以在这里创建一个承诺是可以的。

创建时注意。这样,如果Git.Repository.opengetMasterCommit返回的promise被拒绝,调用者就会看到该拒绝。

这是一个使用async/await的版本。你可以使用await来调用任何返回Promise的函数。注意:prepareDiffs返回一个Promise来包装事件发射器。

    export function prepareDiffs(): Promise<Commit[]> {
        return new Promise<Commit[]>(async (resolve, reject) => {
            var repo = await Git.Repository.open("features/tutorial");
            var masterCommit = await repo.getMasterCommit();
            var history = masterCommit.history();
            var result: Commit[] = [];
            history.on("commmit", commit => {
                var entry = new Commit();
                entry.hash = commit.sha();
                var step = /[0-9].[0-9]/.exec(commit.message());
                if (step !==  null)
                    entry.step = step.toString();
                result.push(entry);
            });
            history.on("end", () => resolve(result));
            history.on("error", err => reject(err));
            history.start();
        });
    }

这样说…

var commits = await prepareDiffs();