如何重用promise?

我正在尝试重用从promise中返回的数据。 但问题是,在第一次调用checkPromise函数后,它立即调用第二个函数,第一个函数的promise没有实现,所以它不会返回任何数据,因此它永远不会进入if子句。 我如何重用诺言?

 var Promise = require('bluebird'); var request = Promise.promisify(require("request")); var url = 'http://www.google.com'; var obj = new Object; function apiCall(url) { return new Promise(function (resolve, reject) { request(url).spread(function(response, body) { return resolve(body); }).catch(function(err) { console.error(err); return reject(err); }); }); } function checkPromise(url) { if(obj.hasOwnProperty(url)) { var rp = obj[url]; //do something } else { apiCall(url).then(function(result) { obj[url] = result; //do something }); } } checkPromise(url); checkPromise(url); 

您可能有时间问题。 你的apiCall()函数是asynchronous的。 这意味着它稍后结束。 因此,每次您调用checkPromise() ,您所做的只是开始一个请求,稍后再结束。 所以,你第一次打电话,它开始一个请求(尚未完成)。 然后,你的下一个调用checkPromise()被调用,这是在第一个调用完成之前检查的。 因此,它在caching中找不到任何东西。

您的代码并行运行两个请求,而不是一个接一个地运行。

如果你真的想等到第一个请求完成后再执行第二个请求,那么你将不得不实际构造你的代码来做到这一点。 您需要使checkPromise()自己返回一个承诺,以便使用它的代码可以在实际完成时知道,以便在执行完成后执行。

仅供参考,在您的代码中,我没有看到任何实际上涉及重复使用承诺的内容(这是您无法做到的,因为它们是一次性对象)。

这是一个可能的实现:

 var Promise = require('bluebird'); var request = Promise.promisify(require("request")); var url = 'http://www.google.com'; var obj = {}; function apiCall(url) { return request(url).spread(function(response, body) { return body; }); } function checkPromise(url) { if(obj.hasOwnProperty(url)) { var rp = obj[url]; //do something return Promise.resolve(rp); } else { return apiCall(url).then(function(result) { obj[url] = result; //do something return result; }); } } checkPromise(url).then(function() { checkPromise(url); }); 

重大变化:

  1. 返回request()返回的promise,而不是另外创build一个。
  2. 更改checkPromise()所以它始终返回一个承诺,无论该值是否在caching中find,所以调用代码可以始终如一地工作。
  3. 对两个checkPromise()调用进行sorting,以便第一个可以在第二个执行之前完成。

如果你感兴趣的结果已经被加载,一个非常不同的方法是实际上等待caching。 这可以这样做:

 var Promise = require('bluebird'); var request = Promise.promisify(require("request")); var url = 'http://www.google.com'; var obj = {}; function apiCall(url) { return request(url).spread(function(response, body) { return body; }); } function checkPromise(url) { if(obj.hasOwnProperty(url)) { // If it's a promise object in the cache, then loading // If it's a value, then the value is already available // Either way, we wrap it in a promise and return that return Promise.resolve(obj[url]); } else { var p = apiCall(url).then(function(result) { obj[url] = result; //do something return result; }); obj[url] = p; return p; } } checkPromise(url).then(function(result) { // use result }); checkPromise(url).then(function(result) { // use result }); 

你的代码有一些问题,首先在apiCall ,你正在做一个承诺ant模式(不需要这个新的承诺),其次你的checkPromise正在做一个同步操作,所以它必须返回一个promise或者有一个callback参数,所以你的代码可以改成:

 var Promise = require('bluebird'); var request = Promise.promisify(require("request")); var url = 'http://www.google.com'; var obj = new Object; function apiCall(url) { return request(url).spread(function(response, body) { return body; }).catch(function(err) { console.error(err); throw err; }); } function checkPromise(url) { var promise = Promise.resolve(); if(obj.hasOwnProperty(url)) { var rp = obj[url]; //do something } else { return apiCall(url).then(function(result) { obj[url] = result; //do something }); } return promise; } checkPromise(url).then(function(){ return checkPromise(url); }); 

鉴于你在全球范围内存储结果的方式,它可能是最容易做到的

 function checkPromise(url) { if (!obj[url]) obj[url] = apiCall(url); obj[url].then(function(result) { //do something }); } 

基本上做出请求,如果它还没有开始,然后附加一个监听器的结果加载的承诺。