Ответ 1
Нативный JavaScript promises не имеет механизма тайм-аута.
Вопрос о вашей реализации, вероятно, будет лучше подходит для http://codereview.stackexchange.com, но несколько примечаний:
-
Вы не предоставляете средства для фактического выполнения обещаний, а
-
Нет необходимости в
clearTimeout
в вашем обратном вызовеsetTimeout
, так какsetTimeout
планирует одноразовый таймер. -
Поскольку обещание не может быть разрешено/отклонено после его разрешения/отклонения, вам не нужна эта проверка.
Так что, возможно, что-то в этом роде:
function myPromise(ms, callback) {
return new Promise(function(resolve, reject) {
// Set up the real work
callback(resolve, reject);
// Set up the timeout
setTimeout(function() {
reject('Promise timed out after ' + ms + ' ms');
}, ms);
});
}
Используется следующим образом:
myPromise(2000, function(resolve, reject) {
// Real work is here
});
(Или вы можете хотеть, чтобы это было немного сложнее, см. обновление в строке ниже.)
Я был бы немного обеспокоен тем фактом, что семантика немного отличается (нет new
, тогда как вы используете new
с конструктором Promise
), поэтому вы можете настроить это.
Другая проблема, конечно, в том, что большую часть времени вы не хотите создавать новый promises, и поэтому не могли бы использовать вышеизложенное. В большинстве случаев у вас есть обещание уже (результат предыдущего вызова then
и т.д.). Но для ситуаций, когда вы действительно строите новое обещание, вы можете использовать что-то вроде выше.
Вы можете иметь дело с темой new
путем подкласса Promise
:
class MyPromise extends Promise {
constructor(ms, callback) {
// We need to support being called with no milliseconds
// value, because the various Promise methods (`then` and
// such) correctly call the subclass constructor when
// building the new promises they return.
// This code to do it is ugly, could use some love, but it
// gives you the idea.
let haveTimeout = typeof ms === "number" && typeof callback === "function";
let init = haveTimeout ? callback : ms;
super((resolve, reject) => {
init(resolve, reject);
if (haveTimeout) {
setTimeout(() => {
reject("Timed out");
}, ms);
}
});
}
}
Использование:
let p = new MyPromise(300, function(resolve, reject) {
// ...
});
p.then(result => {
})
.catch(error => {
});
Живой пример:
// Uses var instead of let and non-arrow functions to try to be
// compatible with browsers that aren't quite fully ES6 yet, but
// do have promises...
(function() {
"use strict";
class MyPromise extends Promise {
constructor(ms, callback) {
var haveTimeout = typeof ms === "number" && typeof callback === "function";
var init = haveTimeout ? callback : ms;
super(function(resolve, reject) {
init(resolve, reject);
if (haveTimeout) {
setTimeout(function() {
reject("Timed out");
}, ms);
}
});
}
}
var p = new MyPromise(100, function(resolve, reject) {
// We never resolve/reject, so we test the timeout
});
p.then(function(result) {
snippet.log("Resolved: " + result);
}).catch(function(reject) {
snippet.log("Rejected: " + reject);
});
})();
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>