Javascript 如何创建返回现有承诺而不是新承诺的函数?

Javascript 如何创建返回现有承诺而不是新承诺的函数?,javascript,closures,promise,es6-promise,Javascript,Closures,Promise,Es6 Promise,JavaScript/Promise专家 我希望您能帮助我,因为我不明白如何创建一个返回现有承诺而不是新承诺的函数。我做了大量的研究,但每次调用函数时,所有示例都会返回一个新的承诺 假设我有一个函数,它需要一些时间来处理,并且每次调用时都会生成不同的结果。当我使用新的promise方法时,我仍然需要等待每次完成,如果我调用函数,我不会得到相同的值 我已经包括了我所创建的能够按预期工作的概念证明(除非我忽略了某些东西)。我认为这个“解决方案”很难看,因为我需要将变量移动到更高的范围,而且每次调用函

JavaScript/Promise专家

我希望您能帮助我,因为我不明白如何创建一个返回现有承诺而不是新承诺的函数。我做了大量的研究,但每次调用函数时,所有示例都会返回一个新的承诺

假设我有一个函数,它需要一些时间来处理,并且每次调用时都会生成不同的结果。当我使用新的promise方法时,我仍然需要等待每次完成,如果我调用函数,我不会得到相同的值

我已经包括了我所创建的能够按预期工作的概念证明(除非我忽略了某些东西)。我认为这个“解决方案”很难看,因为我需要将变量移动到更高的范围,而且每次调用函数时我仍然需要创建一个新的承诺

我此刻的设想;为了使这段代码更好,函数需要返回一个现有的承诺,而不是一个新的承诺,但是如果其他解决方案提供相同的功能和更好的代码,那么请让我知道。首选本地ES6

谢谢

-

- (以下代码基于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);

尝试建议的新变量方法。承诺被设计为单发,因此它取决于实现。您尝试做的更多是在事件或reactivex领域。如果您使用的是jquery,那么您可以使用他们的事件方案。nodejs站点上有一个更干净的方案。因为它不需要运行任何其他内容在浏览器中.rxjs是流处理作物中的精华,但它是一个大型库,需要一些学习。值得一试——因为在许多语言中,相同的知识对客户端和服务器都很有用。您甚至可以通过promise等多种方式来设置流。

您需要的是promise,而不是它解决的价值。Memoisat离子作为结果值

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
在第一次调用时仍将创建一个
randomsyncnumber()
,而不是
notSoRandomAsyncNumber()

使用变量。这就是变量存在的原因。因此您可以多次引用相同的数据。var x=new Promise();function(){return x};谢谢你的回答Jamen。也许我误解了你的答案,但是当你使用承诺作为变量而不是函数时,代码会立即执行,而不是在必要时等待调用。这会导致不希望的副作用。此外,then方法需要函数而不是承诺来防止承诺结果我会通过。等等,所以你希望返回
randomNumber
randomNumberPlusOne
以在每次调用它们时产生相同的数字,而不是随机数???感谢你的精彩回答Bergi!我对编程和JavaScript还是很陌生,我不知道这种技术被称为记忆。在你的answ之后呃,我觉得返回值而不是承诺很愚蠢。根据你的回答,我创建了一个基于闭包的概念证明,以从全局范围中删除变量。你对这种方法有什么看法?(我需要在问题中添加新代码,因为我不允许在评论中添加,我也不熟悉堆栈溢出)是的,使用IEFEs可以为
p
q
创建一个范围。只是感觉有点重复,这就是我写的
memoize
的目的:-)啊,现在noob知道你也在使用闭包。;-(另一个我觉得很愚蠢的时刻)再次感谢你,希望有一天我有你的JavaScript技能,并且能够帮助人们。
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);