我正在尝试重用从promise返回的数据。但是,问题是,在第一次调用checkPromise
函数之后,它立即调用了第二个函数,并且没有满足第一个函数的 promise ,因此它从不返回任何数据,因此也从不输入if子句。我如何重用 promise ?
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()
函数是异步的。这意味着它会在以后的某个时间完成。这样,每次调用checkPromise()
时,您所做的就是启动请求,并在以后的某个时间完成。因此,您第一次调用它,它启动了一个请求(尚未完成)。然后,您的下一个对checkPromise()
的调用将被调用,并在第一个调用完成之前进行if
检查。因此,它尚未在缓存中找到任何内容。
您的代码正在并行运行两个请求,而不是一个接一个。
如果您实际上要等到第一个请求完成后再执行第二个请求,那么您将必须实际构造代码来执行此操作。您需要使checkPromise()
本身返回一个Promise,以便可以在实际完成时知道使用它的代码,以便在完成后执行某些操作。
仅供引用,我在您的代码中看不到任何与重用Promise相关的东西(这是您无法完成的事情,因为它们是一次性的对象)。
这是一种可能的实现:
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);
});
重大更改:
request()
返回的promise,而不是创建另一个promise。 checkPromise()
,以便无论是否在缓存中找到该值,它始终会返回一个保证,因此调用代码始终可以始终如一地工作。 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)) {
// 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
});