自定义 ESLint 规则中的异步代码
Asynchronous code in custom ESLint rules
故事与动机:
我们有一个相当庞大的端到端 Protractor 测试代码库。有时,测试会等待特定修复的实施——通常作为 TDD 方法的一部分,并演示问题是如何重现的以及预期的行为是什么。我们目前正在做的是使用 Jasmine 的 pending()
,里面有一个 Jira 问题编号。示例:
pending("Missing functionality (AP-1234)", function () {
// some testing is done here
});
现在,我们想知道何时可以将 pending()
重命名为 it()
和 运行 测试。或者,换句话说,当问题 AP-1234
已解决或发送至测试时。
当前方法:
目前,我正在尝试用 custom ESLint
rule, jira
NodeJS module, and Q
来解决它。自定义 ESLint
规则搜索带有至少一个参数的 pending()
调用。以 AP-
后跟 4 位数字的格式提取票号,并使用 jira.findIssue()
检查其在 Jira 中的状态。如果状态为 Resolved
- 报告错误。
这是我目前得到的:
"use strict";
var JiraApi = require("jira").JiraApi,
Q = require('q');
var jira = new JiraApi("https",
"jira.url.com",
"443",
"user",
"password",
"2");
module.exports = function (context) {
var jiraTicketRegex = /AP\-\d+/g;
return {
CallExpression: function (node) {
if (node.callee.name === "pending" && node.arguments.length > 0) {
var match = node.arguments[0].value.match(jiraTicketRegex);
if (match) {
match.forEach(function(ticket) {
console.log(ticket); // I see the ticket numbers printed
getTicket(ticket).then(function (status) {
console.log(status); // I don't see statuses printed
if (status === "Resolved") {
context.report(node, 'Ticket {{ticket}} is already resolved.', {
ticket: ticket
})
}
});
});
}
}
}
}
};
其中 getTicket()
定义为:
function getTicket(ticket) {
var deferred = Q.defer();
jira.findIssue(ticket, function(error, issue) {
if (error) {
deferred.reject(new Error(error));
} else {
deferred.resolve(issue.fields.status.name);
}
});
return deferred.promise;
}
问题是: 目前,它成功地从 pending()
调用中提取票号,但不打印票状态。不过没有错误。
问题:
我想一般的问题是:我可以使用异步代码块、等待回调、解决自定义 ESLint
规则中的承诺吗?如果没有,我有什么选择?
一个更具体的问题是:我做错了什么以及如何将 Node.js jira
模块与 ESLint
一起使用?
将不胜感激任何见解或替代方法。
简短的回答是 - 不,您不能在规则内使用异步代码。 ESLint 是同步的,并且在遍历 AST 时严重依赖 EventEmitter
。将 ESLint 代码修改为异步非常困难,但同时又要保证事件将以正确的顺序发出。
我认为您唯一的选择可能是编写一个同步规则,将足够的信息输出到错误消息中,然后使用 JSON
或 UNIX
等可解析格式化程序之一,然后创建另一个可以通过管道传输 ESLint 的应用程序根据错误消息输出并在 Jira 中执行异步查找。
注意:它没有回答关于在 ESLint 自定义规则中支持异步代码的原始问题,而是提供了该问题的替代解决方案。
我个人不会在这种情况下使用 ESLint,它应该用于检查您的代码是否编写正确以及您是否遵循风格指南;从我的角度来看,缺少测试不是代码检查的一部分,它更像是您的团队内部流程。此外,这种请求可能会显着降低您的 ESLint 执行速度,如果有人在他们的编辑器中实时运行它,调用将会非常频繁并且会减慢整个检查。我会让这个 JIRA 检查 Protractor 流程的一部分,所以如果问题单得到解决,你将得到一个失败的 Protractor 规格。 (从 复制来使答案完整)
Jasmine 允许使用 xit()
. I am not sure about pending()
though, it works weird in Protractor. Also, Jasmine allows to call pending()
inside a spec, so it will be marked as pending, but it is not implemented for Protractor yet (see issue) 将规范标记为待定。知道这一点后,我会使用自定义助手来定义 "pending specs",应该检查 JIRA 问题状态。我想你仍然可以使用 Q 来处理承诺,我只是 post 一个使用 WebDriver 承诺的替代方案,没有外部依赖。这是 getTicket()
的修改版本:
function getTicketStatus(ticket) {
// Using WebDriver promises
var deferred = protractor.promise.defer();
jira.findIssue(ticket, function(error, issue) {
if (error) {
deferred.reject(new Error(error));
} else {
deferred.fulfill(issue.fields.status.name);
}
});
return deferred.promise;
}
然后就是自定义辅助函数:
function jira(name) {
// Display as pending in reporter results, remove when pending() is supported
xit(name);
// Using Jasmine Async API because Jira request is not a part of Control Flow
it(name, function (done) {
getTicketStatus().then(function (status) {
if (status === 'Resolved') {
done.fail('Ticket "' + name + '" is already resolved.');
} else {
done();
// pending() is not supported yet https://github.com/angular/protractor/issues/2454
// pending();
}
}, function (error) {
done.fail(error);
});
});
}
用法示例:
jira('Missing functionality (AP-1234)', function () {
//
});
jira('Missing functionality (AP-1235)');
如果对 JIRA 的请求失败或问题的状态为 Resolved,您将得到一个失败的规范(使用 茉莉 async API). In all situations you will still have this spec duplicated as pending in reporter results. I hope it can be improved, when pending()
functionality inside a spec is implemented.
这些答案在 2018 年仍然有效。
有关 eslint 开发人员的一些见解,请参阅 this conversation 我们在他们的邮件列表中。
举一个有效的例子,在我的 "pseudo eslint plugin" 中,我选择使用昂贵但同步的 API,并警告用户如何最好地在他们的 CI 过程中使用 "plugin"。
故事与动机:
我们有一个相当庞大的端到端 Protractor 测试代码库。有时,测试会等待特定修复的实施——通常作为 TDD 方法的一部分,并演示问题是如何重现的以及预期的行为是什么。我们目前正在做的是使用 Jasmine 的 pending()
,里面有一个 Jira 问题编号。示例:
pending("Missing functionality (AP-1234)", function () {
// some testing is done here
});
现在,我们想知道何时可以将 pending()
重命名为 it()
和 运行 测试。或者,换句话说,当问题 AP-1234
已解决或发送至测试时。
当前方法:
目前,我正在尝试用 custom ESLint
rule, jira
NodeJS module, and Q
来解决它。自定义 ESLint
规则搜索带有至少一个参数的 pending()
调用。以 AP-
后跟 4 位数字的格式提取票号,并使用 jira.findIssue()
检查其在 Jira 中的状态。如果状态为 Resolved
- 报告错误。
这是我目前得到的:
"use strict";
var JiraApi = require("jira").JiraApi,
Q = require('q');
var jira = new JiraApi("https",
"jira.url.com",
"443",
"user",
"password",
"2");
module.exports = function (context) {
var jiraTicketRegex = /AP\-\d+/g;
return {
CallExpression: function (node) {
if (node.callee.name === "pending" && node.arguments.length > 0) {
var match = node.arguments[0].value.match(jiraTicketRegex);
if (match) {
match.forEach(function(ticket) {
console.log(ticket); // I see the ticket numbers printed
getTicket(ticket).then(function (status) {
console.log(status); // I don't see statuses printed
if (status === "Resolved") {
context.report(node, 'Ticket {{ticket}} is already resolved.', {
ticket: ticket
})
}
});
});
}
}
}
}
};
其中 getTicket()
定义为:
function getTicket(ticket) {
var deferred = Q.defer();
jira.findIssue(ticket, function(error, issue) {
if (error) {
deferred.reject(new Error(error));
} else {
deferred.resolve(issue.fields.status.name);
}
});
return deferred.promise;
}
问题是: 目前,它成功地从 pending()
调用中提取票号,但不打印票状态。不过没有错误。
问题:
我想一般的问题是:我可以使用异步代码块、等待回调、解决自定义 ESLint
规则中的承诺吗?如果没有,我有什么选择?
一个更具体的问题是:我做错了什么以及如何将 Node.js jira
模块与 ESLint
一起使用?
将不胜感激任何见解或替代方法。
简短的回答是 - 不,您不能在规则内使用异步代码。 ESLint 是同步的,并且在遍历 AST 时严重依赖 EventEmitter
。将 ESLint 代码修改为异步非常困难,但同时又要保证事件将以正确的顺序发出。
我认为您唯一的选择可能是编写一个同步规则,将足够的信息输出到错误消息中,然后使用 JSON
或 UNIX
等可解析格式化程序之一,然后创建另一个可以通过管道传输 ESLint 的应用程序根据错误消息输出并在 Jira 中执行异步查找。
注意:它没有回答关于在 ESLint 自定义规则中支持异步代码的原始问题,而是提供了该问题的替代解决方案。
我个人不会在这种情况下使用 ESLint,它应该用于检查您的代码是否编写正确以及您是否遵循风格指南;从我的角度来看,缺少测试不是代码检查的一部分,它更像是您的团队内部流程。此外,这种请求可能会显着降低您的 ESLint 执行速度,如果有人在他们的编辑器中实时运行它,调用将会非常频繁并且会减慢整个检查。我会让这个 JIRA 检查 Protractor 流程的一部分,所以如果问题单得到解决,你将得到一个失败的 Protractor 规格。 (从
Jasmine 允许使用 xit()
. I am not sure about pending()
though, it works weird in Protractor. Also, Jasmine allows to call pending()
inside a spec, so it will be marked as pending, but it is not implemented for Protractor yet (see issue) 将规范标记为待定。知道这一点后,我会使用自定义助手来定义 "pending specs",应该检查 JIRA 问题状态。我想你仍然可以使用 Q 来处理承诺,我只是 post 一个使用 WebDriver 承诺的替代方案,没有外部依赖。这是 getTicket()
的修改版本:
function getTicketStatus(ticket) {
// Using WebDriver promises
var deferred = protractor.promise.defer();
jira.findIssue(ticket, function(error, issue) {
if (error) {
deferred.reject(new Error(error));
} else {
deferred.fulfill(issue.fields.status.name);
}
});
return deferred.promise;
}
然后就是自定义辅助函数:
function jira(name) {
// Display as pending in reporter results, remove when pending() is supported
xit(name);
// Using Jasmine Async API because Jira request is not a part of Control Flow
it(name, function (done) {
getTicketStatus().then(function (status) {
if (status === 'Resolved') {
done.fail('Ticket "' + name + '" is already resolved.');
} else {
done();
// pending() is not supported yet https://github.com/angular/protractor/issues/2454
// pending();
}
}, function (error) {
done.fail(error);
});
});
}
用法示例:
jira('Missing functionality (AP-1234)', function () {
//
});
jira('Missing functionality (AP-1235)');
如果对 JIRA 的请求失败或问题的状态为 Resolved,您将得到一个失败的规范(使用 茉莉 async API). In all situations you will still have this spec duplicated as pending in reporter results. I hope it can be improved, when pending()
functionality inside a spec is implemented.
这些答案在 2018 年仍然有效。
有关 eslint 开发人员的一些见解,请参阅 this conversation 我们在他们的邮件列表中。
举一个有效的例子,在我的 "pseudo eslint plugin" 中,我选择使用昂贵但同步的 API,并警告用户如何最好地在他们的 CI 过程中使用 "plugin"。