这是 Deferred 的一个很好的用例吗?
Is this a good use case for a Deferred?
我经常听到有人将 Deferred
描述为 'anti-pattern'(例如 here)。
我试图了解我是否有使用延迟有意义的场景,也许你可以提供帮助。我在单页网络应用程序的页面上有一个 recaptcha。要执行某些操作,需要通过验证码测试。由于验证码在一段时间后过期,用户可能需要重做测试。但有时用户可能会在验证码过期之前触发这些操作之一,因此不应重做测试。下面是一些伪代码,以便更好地理解:
class App {
constructor () {
this.captchaPromise = new Deferred();
}
maybeDoIt () {
this.captchaPromise.then(() => {
this._doIt();
})
}
_doIt () {
alert('done');
}
_onCaptchaSuccess () {
this.captchaPromise.resolve();
}
_onCaptchaExpire () {
this.captchaPromise.reject();
this.captchaPromise = new Deferred();
}
}
const app = new App();
window._captchaOnload = function () {
window.grecaptcha.render('js-captcha', {
'sitekey': 'dsadaablsabllbalblablalblablablalbalbalblablabla31',
'callback': app._onCaptchaSuccess.bind(app),
'expired-callback': app._onCaptchaExpire.bind(app)
});
};
您认为这是实现上述场景的好方法吗?
我也在努力寻找支持 es6 模块导入语法并且至少支持 IE9 及更高版本的 vanilla js 延迟实现或库,即使 IE8 也很棒(我不能使用 jQuery) .非常感谢任何帮助。
更新:
谢谢你的回答,最后我决定我根本不需要承诺。不过,承诺重新验证渲染是个好主意。我解决了以下问题:
_doIt (data) {
if (!this._captchaSolved) {
this._dataToUseAfterCaptchaSuccess = data;
return;
}
this._dataToUseAfterCaptchaSuccess = null;
console.log('done', data);
}
_onCaptchaSuccess (captchaResponse) {
this._captchaSolved = true;
this._captchaResponse = captchaResponse;
if (this._dataToUseAfterCaptchaSuccess) {
this._doIt(this._dataToUseAfterCaptchaSuccess);
}
}
_onCaptchaExpire () {
this._captchaSolved = false;
}
据我所知,没有必要使用 Deferred。
正如所写,它做了两件事,这两件事都可以更简单地实现:
- 作为状态指示符:'pending' 实际上表示 'unexpired',而 'rejected' 表示 'expired'。可以改用简单的布尔值。
- 作为调用
_doIt()
的一种方式:可以直接从 _onCaptchaSuccess
处理程序调用,甚至可以指定为 .render 的 'callback' 处理程序。
更现实的方法是承诺 window.grecaptcha.render()
,例如:
window._captchaOnload = function () {
new Promise(function(resolve, reject) {
window.grecaptcha.render('js-captcha', {
'sitekey': 'dsadaablsabllbalblablalblablablalbalbalblablabla31',
'callback': resolve,
'expired-callback': reject
});
})
.then(app._doIt.bind(app), app.expire.bind(app));
};
app
需要相应地写,不涉及 Deferreds 或 promises。
我经常听到有人将 Deferred
描述为 'anti-pattern'(例如 here)。
我试图了解我是否有使用延迟有意义的场景,也许你可以提供帮助。我在单页网络应用程序的页面上有一个 recaptcha。要执行某些操作,需要通过验证码测试。由于验证码在一段时间后过期,用户可能需要重做测试。但有时用户可能会在验证码过期之前触发这些操作之一,因此不应重做测试。下面是一些伪代码,以便更好地理解:
class App {
constructor () {
this.captchaPromise = new Deferred();
}
maybeDoIt () {
this.captchaPromise.then(() => {
this._doIt();
})
}
_doIt () {
alert('done');
}
_onCaptchaSuccess () {
this.captchaPromise.resolve();
}
_onCaptchaExpire () {
this.captchaPromise.reject();
this.captchaPromise = new Deferred();
}
}
const app = new App();
window._captchaOnload = function () {
window.grecaptcha.render('js-captcha', {
'sitekey': 'dsadaablsabllbalblablalblablablalbalbalblablabla31',
'callback': app._onCaptchaSuccess.bind(app),
'expired-callback': app._onCaptchaExpire.bind(app)
});
};
您认为这是实现上述场景的好方法吗?
我也在努力寻找支持 es6 模块导入语法并且至少支持 IE9 及更高版本的 vanilla js 延迟实现或库,即使 IE8 也很棒(我不能使用 jQuery) .非常感谢任何帮助。
更新:
谢谢你的回答,最后我决定我根本不需要承诺。不过,承诺重新验证渲染是个好主意。我解决了以下问题:
_doIt (data) {
if (!this._captchaSolved) {
this._dataToUseAfterCaptchaSuccess = data;
return;
}
this._dataToUseAfterCaptchaSuccess = null;
console.log('done', data);
}
_onCaptchaSuccess (captchaResponse) {
this._captchaSolved = true;
this._captchaResponse = captchaResponse;
if (this._dataToUseAfterCaptchaSuccess) {
this._doIt(this._dataToUseAfterCaptchaSuccess);
}
}
_onCaptchaExpire () {
this._captchaSolved = false;
}
据我所知,没有必要使用 Deferred。
正如所写,它做了两件事,这两件事都可以更简单地实现:
- 作为状态指示符:'pending' 实际上表示 'unexpired',而 'rejected' 表示 'expired'。可以改用简单的布尔值。
- 作为调用
_doIt()
的一种方式:可以直接从_onCaptchaSuccess
处理程序调用,甚至可以指定为 .render 的 'callback' 处理程序。
更现实的方法是承诺 window.grecaptcha.render()
,例如:
window._captchaOnload = function () {
new Promise(function(resolve, reject) {
window.grecaptcha.render('js-captcha', {
'sitekey': 'dsadaablsabllbalblablalblablablalbalbalblablabla31',
'callback': resolve,
'expired-callback': reject
});
})
.then(app._doIt.bind(app), app.expire.bind(app));
};
app
需要相应地写,不涉及 Deferreds 或 promises。