Javascript 跨多个承诺链保留数据

Javascript 跨多个承诺链保留数据,javascript,scope,promise,Javascript,Scope,Promise,我正在学习承诺,所以我决定尝试扩展它们。一切都正常,只是我很难弄清楚如何使值在所有函数中持久化 我的目标是从这个承诺中找到被调用函数的数量,但是每次调用都会创建一个新函数,我很难找到一种方法来传递值。我尝试添加一个构造函数,该构造函数将传入一个值,但它似乎并不像我预期的那样工作。我想这是因为我误解了“这个”的范围 总而言之,我的每个函数“init”、“add”和“commit”都应该在“totalnumber of steps”变量前面加上1,在本例中,现在的变量是“i”。有了这些,我想说,我在

我正在学习承诺,所以我决定尝试扩展它们。一切都正常,只是我很难弄清楚如何使值在所有函数中持久化

我的目标是从这个承诺中找到被调用函数的数量,但是每次调用都会创建一个新函数,我很难找到一种方法来传递值。我尝试添加一个构造函数,该构造函数将传入一个值,但它似乎并不像我预期的那样工作。我想这是因为我误解了“这个”的范围

总而言之,我的每个函数“init”、“add”和“commit”都应该在“totalnumber of steps”变量前面加上1,在本例中,现在的变量是“i”。有了这些,我想说,我在第1步,第3步,第2步,第3步等等

class Repo {
    constructor(setup) {
        this.s = {};
        this.s._progress = { "total":0, "count":0 };
        this.s._logging = { "enabled":true, "location":"console", "pretty":true, "verbose":false, "tabCount":0 };
        this.s._remoteInfo = { "name":"", "url":"" };
        this.s._localInfo = { "path":"" };

        this.s._logReset = () => {
            this.s._logging.tabCount = 0;
        };

        this.s._log = (message, tabCount) => {
            if(this.s._logging.enabled) {
                let tabs = '';

                if(this.s._logging.pretty) {
                    for(let i = 0; i < tabCount; i++) { tabs = tabs + '\t' };
                }

                if(this.s._logging.location == 'console') { console.log(tabs, message); }
                else {
                    //TODO: implement the file location to output
                }
            }
        };

        this.s._progressReset = () => {
            this.s._progress.total = 0;
            this.s._progress.count = 0;
        };

        this.s._addProgressTotal = () => {
            this.s._progress.total++;
            console.log(this.s._progress.total)
        }

        this.s._addProgress = () => {
            this.s._progress.count++;
            console.log('Progress is ' + this.s._progress.count + ' out of ' + this.s._progress.total)
        }
    }

    //Starts the promise chain and passes in the settings to be used.
    start() {
        this.s._logReset();
        this.s._progressReset();

        return new RepoPromise((resolve, reject) => {
            this.s._log('Start Log: <time>',0)
            resolve(this.s);
        });
    }
}

class RepoPromise extends Promise {
    constructor(executor, val) {
        let e = executor || function (res, rej) { res('')};
        super((resolve, reject) => {
            return e(resolve, reject);
        });

        this.i = val || 0;
    }

    end() {
        const returnValue = super.then((s) => {
            return new RepoPromise((resolve, reject) => {
                s._log('End Log: <time>',0)
                resolve(s);
            }, this.i);
        });
        return returnValue;
    }

    init() {
        //I know I need to add 1 to "i" here, but it won't work
        const returnValue = super.then((s) => {
            return new RepoPromise((resolve, reject) => {
                s._log('git init',1);
                s._addProgress();
                resolve(s, '')
            }, ++this.i);
        });
        return returnValue;
    };

    add() {
        //I know I need to add 1 to "i" here, but it won't work
        const returnValue = super.then((s) => {
            return new RepoPromise((resolve, reject) => {
                setTimeout(() => {
                    s._log('git add',1);
                    s._addProgress();
                    resolve(s,'');
                    //reject('Add Failed')
                }, Math.random() * (10000 - 1000) + 1000);
            },++this.i);
        });
        return returnValue;
    }

    commit() {
        //I know I need to add 1 to "i" here, but it won't work
        const returnValue = super.then((s) => {
            return new RepoPromise((resolve, reject) => {
                setTimeout(() => {
                    s._log('git commit -m "message"',1);
                    s._addProgress();
                    resolve(s, 'Finished');
                }, Math.random() * (5000 - 1000) + 1000);
            }, ++this.i);
        });
        return returnValue;
    }

    then(onFulfilled, onRejected) {
        const returnValue = super.then(onFulfilled, onRejected);
        return returnValue;
    }
}

正如您所指出的,这个链条中没有一个承诺,每个
然后
捕获都会返回一个新的承诺。因此,不要试图将状态保留在
RepoPromise
中,而是将其保留在通过链的对象中作为分辨率值:
s

Re是
RepoPromise
构造函数的第二个参数:您不能可靠地执行此操作,因为您无法控制每次调用该构造函数。请记住,当您调用
然后
catch
时,将调用该构造函数。这是在
s
上传递值的另一个原因。:-)为了完整起见,这里举例说明了在
Promise
中调用构造函数的事实:

类MyPromise扩展了Promise{
构造函数(…参数){
超级(…args);
log(“调用MyPromise构造函数”);
}
}
我的承诺
。然后(val=>val)
。然后(val=>val)

。然后(val=>val)谢谢您的代码建议,我将进行更改。我发现使用“resolve”来传递设置(“S”)的唯一问题是,它强制它位于“then”呼叫中,这不允许我提前计算呼叫数。我需要在每次调用的开始处添加值,然后才能返回链接。所以,除非有一个技工来做,否则我不知道怎么做。这就是为什么我尝试采用构造函数的方式,这显然给我带来了问题。@Krum110487:恐怕我不明白“提前”将调用相加是什么意思……?所以当调用add/init/commit时,我会在我希望将计数加1的地方加上注释。如果加法发生在那里,它会在第一次调用结束之前加上3次,因为我们正在等待promise回调。因为Add/init/commit在返回承诺后将继续进行,所以我希望计数发生在Add/init/commit函数本身,而不是它们返回的承诺中。@Krum110487:我可能太密集了。您说过“我的目标是从这个承诺中找到被调用函数的数量……”您具体想计算对哪些函数的调用<代码>添加
?或者
然后
/
捕获
?(在您的示例中,
commit
之后,只有最后一个
catch
,所以您的目标可能是计算
添加
调用数?)!要是当初我能说得这么简单就好了。
var p = new Repo('')
.start()
    .init()
    .add()
    .commit()
.end()
.catch(
    x => {console.log('it broke: ' + x)}
);