【问题标题】:Break promise chain into seperate functions将 Promise 链分解为单独的函数
【发布时间】:2017-01-24 22:14:12
【问题描述】:

分成两个功能:

public valJson(json, schemaFile: string) {
    return new Promise((resolve, reject) => {
        this.http.get(schemaFile)
            .toPromise()
            .then(fileContents => fileContents.json())
            .then((schema) => {
                let ajv = new Ajv({allErrors: true});
                ajv.validate(schema, json) ? 
                resolve() :
                reject(new Error("JSON does not conform to schema: " + ajv.errorsText()));
            }, err => reject(
                new Error("Unable to get schema file contents:" + err))
            );
    });
};

这个函数确实做了 3 件事,所以它不是很好的单元测试。

  1. 获取文件内容
  2. 将它们解析为 json
  3. 验证 json

如何分解以使这些任务中的每一个都可进行单元测试?

尝试 1 打破实际验证部分并不顺利:

public valJson(json, schemaFile: string) {
    return new Promise((resolve, reject) => {
        this.http.get(schemaFile)
            .toPromise()
            .then(fileContents => fileContents.json())
            .then((schema) => {
                this.valJ(schema)
            }, err => reject(
                new Error("Unable to get schema file contents:" + err))
            );
    });
};

    valJ(schema, json) {
        let ajv = new Ajv({ allErrors: true });
        if ajv.validate(schema, json) 
            return resolve()
        reject(new Error("JSON does not conform to schema: " + ajv.errorsText()));
    }
}

更新 - 根据反馈,我正在尝试停止使用匿名函数,然后我将尝试不创建新的承诺。我来了:

public valJson(json, schemaFile: string) {
    return new Promise((resolve, reject) => {
    var getFilePromise = this.http.get(schemaFile)
            .toPromise();
    var parseToJsonPromise = getFilePromise
            .then(contents => this.toJson(contents));
    var validateJsonPromise = parseToJsonPromise.then(schema => this.valJ(schema, json, resolve, reject),
            err => reject(
                new Error("Unable to get schema file contents:" + err))
            );
    });
};

toJson(fileContents): any {
    return fileContents.json()
}

valJ(schema, json, resolve, reject): any {
    let ajv = new Ajv({ allErrors: true });
    ajv.validate(schema, json) ?
        resolve() :
        reject(new Error("JSON does not conform to schema: " + ajv.errorsText())
    );
}

【问题讨论】:

  • 你正在做承诺反模式(谷歌它)。 .http.get().toPromise() 返回一个承诺,所以不要自己创建new Promise()。而是只返回.http.get().toPromise()返回的承诺;
  • 您的匿名函数不必是匿名的。您可以将它们分解为具有众所周知的输入和预期输出的单独定义的函数。然后,您只需将单独声明的函数的名称放入实现中。然后,您可以分别测试它们中的每一个。唯一变得困难的是如果您使用来自父范围的变量。然后,将代码分解为更高范围内单独声明的函数的唯一方法,您可以在其中独立调用它们,是将这些变量传递给它们,而不是直接从父范围使用它们。
  • 我投票结束这个问题,因为它属于 codereview.stackexchange.com

标签: javascript typescript promise


【解决方案1】:

一种可能的方法:

public valJson(json, schemaFile: string) {
  return this.fetchSchema(schemaFile)
    .then(res => this.parseSchema(res))
    .then(schema => this.validateWithSchema(json, schema));
}

fetchSchema(url) {
  return this.http.get(url).toPromise();
}

parseSchema(response) {
  return response.json();
}

validateWithSchema(json, schema) {
  let ajv = new Ajv({allErrors: true});
  if (!ajv.validate(schema, json)) {
    throw new Error("JSON does not conform to schema: " + ajv.errorsText())
  }
}

【讨论】:

    猜你喜欢
    • 2011-05-02
    • 2016-05-09
    • 2020-01-12
    • 2022-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    相关资源
    最近更新 更多