如何创建一个返回现有承诺而不是新承诺的函数
How to create a function that returns an existing promise instead of new promise?
JavaScript/Promise专家
我希望你能帮助我,因为我不明白我怎么能创建一个函数,返回一个现有的承诺,而不是一个新的承诺。我已经做了很多的研究,但所有的例子返回一个新的承诺每次函数被调用。
假设我有一个函数,它需要一些时间来处理,并且每次调用它都会生成不同的结果。当我使用新的promise方法时,我仍然需要等待每次完成,如果我调用函数,我不会得到相同的值。
我已经包含了我所创建的概念证明,如预期的那样工作(除非我忽略了一些东西)。我认为这个"解决方案"是丑陋的,因为我需要将变量移动到更高的范围,我仍然需要在每次调用函数时创建一个新的承诺。
我此刻的假设;为了使这个漂亮的代码函数需要返回一个现有的承诺,而不是一个新的,但如果其他解决方案提供相同的功能和更好的代码,那么请让我知道。首选原生ES6。
谢谢!
'use strict';
var p;
var q;
var randomNumber = function() {
return new Promise(function(resolve) {
console.log(`p: ${p}`);
if (typeof p === 'undefined') {
setTimeout(function() {
p = Math.random();
resolve(p);
}, 1000);
} else {
resolve(p);
}
});
};
var randomNumberPlusOne = function() {
return new Promise(function(resolve) {
console.log(`q: ${q}`);
if (typeof q === 'undefined') {
randomNumber()
.then(function(p) {
q = p + 1;
resolve(q);
});
} else {
resolve(q);
}
});
};
var showResult = function(result) {
console.log();
console.log(`r: ${result}`);
};
randomNumber()
.then(showResult);
randomNumber()
.then(randomNumberPlusOne)
.then(showResult);
randomNumberPlusOne()
.then(showResult);
setTimeout(function() {
console.log();
console.log('setTimeout:');
console.log();
randomNumber()
.then(showResult);
randomNumber()
.then(randomNumberPlusOne)
.then(showResult);
randomNumberPlusOne()
.then(showResult);
}, 2000);
- - -(下面的代码是基于Bergi的反馈;
'use strict';
var randomNumber = (function() {
var p = null;
return function() {
console.log('p:');
console.log(p);
console.log();
if (!p) {
p = new Promise(function(resolve) {
setTimeout(function() {
resolve(Math.random());
}, 1000);
});
}
return p;
};
})();
var randomNumberPlusOne = (function() {
var q = null;
return function() {
console.log('q:');
console.log(q);
console.log();
if (!q) {
q = randomNumber()
.then(function(p) {
return p + 1;
});
}
return q;
};
})();
var showResult = function(result) {
console.log(`r: ${result}`);
console.log();
};
randomNumber()
.then(showResult);
randomNumber()
.then(randomNumberPlusOne)
.then(showResult);
randomNumberPlusOne()
.then(showResult);
setTimeout(function() {
console.log();
console.log('setTimeout:');
console.log();
randomNumber()
.then(showResult);
randomNumber()
.then(randomNumberPlusOne)
.then(showResult);
randomNumberPlusOne()
.then(showResult);
}, 2000);
您需要记住承诺,而不是它解析的值。记忆可以很好地将承诺作为结果值。
var p = null;
function notSoRandomAsyncNumber() {
if (!p)
p = new Promise(function(resolve) {
setTimeout(function() {
resolve(Math.random());
}, 1000);
});
return p;
}
或者抽象为辅助函数:
function memoize(fn) {
var cache = null;
return function memoized(args) {
if (fn) {
cache = fn.apply(this, arguments);
fn = null;
}
return cache;
};
}
function randomAsyncNumber() {
return new Promise(res => {
setTimeout(() => resolve(Math.random()), 1000);
});
}
function randomAsyncNumberPlusOne() {
return randomAsyncNumber().then(n => n+1);
}
var notSoRandomAsyncNumber = memoize(randomAsyncNumber);
var notSoRandomAsyncNumberPlusOne = memoize(randomAsyncNumberPlusOne);
(注意notSoRandomAsyncNumberPlusOne
仍然会在第一次调用时创建randomAsyncNumber()
,而不是notSoRandomAsyncNumber()
)
尝试建议的新变量方法。承诺被设计成一次性的,所以它取决于实现。你要做的更多的是在事件或反应的舞台上。如果你正在使用jquery,那么你可以使用他们的事件方案。nodejs网站上有一个更简洁的。因为它不需要其他任何东西,所以它在浏览器中运行。RXJS是流处理领域的精华,但它是一个很大的库,需要一些学习。值得这样做——因为相同的知识在许多语言的客户机和服务器中都是有用的。你甚至可以从承诺中建立一个流——在许多其他方法中。
- 猫鼬承诺和Q承诺
- JavaScript中的延期/承诺概念是一个新的概念,还是函数式编程的传统部分
- Chai正如承诺:当承诺抛出错误时,处理错误
- AngularJS决心承诺.如果承诺被拒绝,则重定向
- 传播承诺并在新对象中扩展
- 承诺返回承诺
- 承诺返回承诺
- 来自 NodeJS 延迟的一系列承诺的承诺
- 我是否可以假设承诺中的错误会冒泡到新的承诺并抓住它
- 基于另一个承诺解决承诺
- 重构:从值或现有承诺返回承诺
- 我如何运行async承诺没有承诺地狱
- 是否有一种直接的方法可以让jQuery动画在集合上创建一个新的承诺?
- AngularJs的承诺&;then &;承诺之前的火焰已被化解
- 多个承诺错误(承诺必须通过new构造)
- 承诺加入添加新的函数调用链
- while(true)循环中的承诺/等待承诺解决
- 如何创建一个返回现有承诺而不是新承诺的函数
- 猫鼬有什么区别.承诺和承诺
- 生成一个依赖于递归承诺的承诺