在我的服务器应用程序中,我想要返回"禁止"当用户没有端点权限时的值。
为此,我创建了一个被拒绝的重用承诺:
let element = document.createElement('div')
element.setAttribute('class', '{a}')
element.setAttribute('id', '{a}')
element.setAttribute('data-x', '{b}')
let data = {
a: 'ok',
b: 'okok'
}
injector(element, data)
console.log(
`${element.outerHTML} === <div class="ok" id="ok" data-x="okok"></div>`,
element.outerHTML === '<div class="ok" id="ok" data-x="okok"></div>'
)
function injector (htmlElement, data) {
let allAttributes = getAllAttributes(htmlElement)
let reduced = allAttributes.reduce((acc, currentAttribute) => {
let currentAttributeValue = htmlElement
.getAttribute(currentAttribute)
.replace(/(\{)|(\})/g, '')
if (acc.hasOwnProperty(currentAttributeValue)) {
acc[currentAttributeValue] = acc[currentAttributeValue].concat(currentAttribute)
} else {
acc[currentAttributeValue] = [currentAttribute]
}
return acc
}, {})
Object.keys(reduced)
.forEach(key => {
reduced[key].forEach(attribute => {htmlElement.setAttribute(attribute, data[key])})
})
}
function getAllAttributes (htmlElement) {
let outerHtml = htmlElement.outerHTML
let tagName = htmlElement.tagName
let outerHtmlWithoutTagName = outerHtml.replace(
new RegExp(tagName.toLowerCase(), 'g')
, ''
)
return outerHtmlWithoutTagName.replace(
/(="{([\w|.]+)}")|(\<|\>|\/)/g
, ''
)
.trim()
.split(' ')
}
然后应用程序中的其他地方:
export const forbidden = Promise.reject(new Error('FORBIDDEN'))
然而,当我启动我的应用程序时,我收到警告
import {forbidden} from './utils'
...
resolve: (root, {post}, {db, isCollab}) => {
if (!isCollab) return forbidden
return db.posts.set(post)
},
我怎样才能告诉Node这个Promise可以不被处理?
答案 0 :(得分:3)
我创建了一个被拒绝的重用承诺
嗯,不要,创建一个重用函数可能要容易得多:
export function forbidden() { return Promise.reject(new Error('FORBIDDEN')); }
每次调用它时,也会为错误提供适当的堆栈跟踪。
我怎样才能告诉Node这个Promise可以不被处理?
只是无所事事地处理它:
export const forbidden = Promise.reject(new Error('FORBIDDEN'));
forbidden.catch(err => { /* ignore */ }); // mark error as handled
(并且不要忘记包含关于这个看似无操作声明的目的的评论)。
答案 1 :(得分:1)
我会提出偏离公认答案的建议。我不建议使用return
语句来提供Error
-这忽略了throw
的确切意图!
我认为您的直觉和接受的答案都经过精心设计。只需执行以下操作即可:
if (!isCollab) throw new Error('FORBIDDEN');
如果您不希望进行堆栈跟踪,则无需考虑所有开销,只需执行以下操作:
if (!isCollab) throw 'FORBIDDEN';
答案 2 :(得分:0)
OP的用法没有完全描述,但是OP的注释“顺便说一句,我不想为每个禁止的错误创建堆栈跟踪,因为我不想泄漏有关我的应用程序的详细信息。我宁愿只创建一次拒绝。” 使我相信,OP的动机至少有一部分是防止未处理的forbidden
拒绝导致信息泄漏。
返回被拒绝(但被拒绝)的诺言在同步功能与异步功能中的行为有所不同。在前者中,诺言是逐字返回的。在后者中,将其重新包装为承诺并自动重新抛出(等同于从函数内部抛出)。 。 。 。
返回forbidden
时,同步功能与异步功能之间的行为差异:
async function test(){
try {
let a = await (async()=>{return forbidden;})();
} catch(e){console.log(e.message);} // outputs: 'FORBIDDEN'
try {
let a = (()=>{return forbidden;})();
// error undetected
} catch(e){console.log(e.message);} // never reaches here !!!
console.log("something else"); // outputs: something else
let a=(()=>{return forbidden;})(); // UHR + '#<Promise>' + no addr
console.log("something else"); // outputs: something else
await (async()=>{return forbidden;})(); // UHR + '#<Promise>' + no addr leak}
}
test();
下面的工厂函数makeError
将提供一个通用的解决方案,它基于OP的原始灵感:
const verboten=new Error('verbotten');
const makeError = () => verboten;
async function test2(){
try {
await (async()=>{throw makeError();})();
} catch(e){console.log(e.message);} // outputs: 'verboten'
// uncomment the following to trigger UHR (unhandled rejection)
//await (async()=>{throw makeError();})(); // UHR + 'verboten' + no addr leak
}
请注意,makeError
返回常量对象verboten
,而不是其自身。 (是的,这是允许的,尽管很少使用。)因此,堆栈跟踪是一个固定值,与程序中的错误位置无关,就像原始OP的forbidden
一样。
这对于发行版本来说很好,但是对于开发版本,可以对makeError
进行较小的更改,在该版本中查看堆栈很有用:
const makeError = Error;