Javascript 如何创建一个处理两个承诺然后返回一个承诺的类?
我想创建一个类,其职责是轮询数据源,将信息整理成一个“警报”对象数组,然后将这些警报的子集传递给需要它们的任何其他类 因为轮询是异步进行的(我正在从web服务请求数据),所以我假设我实际需要返回的是一个承诺,当该承诺实现时,将给出警报对象的正确子集 但很明显,我不明白怎么做,因为应该返回承诺的方法会返回其他东西 这是到目前为止我的代码。如您所见,我正在尝试将承诺存储在实例属性中,然后检索它:Javascript 如何创建一个处理两个承诺然后返回一个承诺的类?,javascript,react-native,es6-promise,Javascript,React Native,Es6 Promise,我想创建一个类,其职责是轮询数据源,将信息整理成一个“警报”对象数组,然后将这些警报的子集传递给需要它们的任何其他类 因为轮询是异步进行的(我正在从web服务请求数据),所以我假设我实际需要返回的是一个承诺,当该承诺实现时,将给出警报对象的正确子集 但很明显,我不明白怎么做,因为应该返回承诺的方法会返回其他东西 这是到目前为止我的代码。如您所见,我正在尝试将承诺存储在实例属性中,然后检索它: export class AlertCollection { constructor() {
export class AlertCollection {
constructor() {
this.alerts = null;
}
// poll the data sources for alert data; store a promise that resolves
// to an array of alerts
poll() {
this.alerts = this.pollTeapot()
.then( (arr) => {this.pollDeliverance(arr);} );
}
// return a promise that fulfils to an array of the alerts you want
filteredAlerts(filter) {
return this.alerts; // not filtering for now
}
// return a promise that fulfills to the initial array of alerts
pollTeapot() {
let process = (json) => {
json2 = JSON.parse(json);
return json2.map( (a) => new Alert(a) );
};
message = new MessageHandler("teapot", "alerts")
return message.request().then( (json) => {process(json);} );
}
// Modify the alerts based on the response from Deliverance.
// (But for the time being let's not, and say we did.)
pollDeliverance(alerts) {
return alerts;
}
}
message.request()
从web服务返回承诺。这很有效。如果我在pollTeapot()
中快照进程
函数,我会得到正确的数据
但是,如果我从filteredAlerts()
快照返回值,我就不会得到它。我也没有得到null(这至少是有意义的,尽管它是错误的。)我得到了类似于{{u45:0、\u81:0、\u65:null、\u54:null}
在这一点上,任何指点都将不胜感激。(顺便说一句,这是React Native,如果有帮助的话。)这将是一个很难描述的例子-我有一个工作示例,但它很复杂,因为我必须“模拟”所有异步部分,并使用
函数类,而不是类关键字-但想法是一样的
这个答案有两个部分
将警报
存储为实例变量没有意义。它们是异步的,在异步调用完成之前不会存在
您需要将所有行为链接到对poll
一般来说,你会像这样把承诺彼此联系在一起
functionWhichReturnsPromise()
.then(functionPointer)
.then(function(result){
// some functionality, which can return anything - including another promise
});
所以你的代码最终看起来像
var alertCollection = new AlertCollection()
alertCollection.poll().then(function(alerts){
//here alerts have been loaded, and deliverance checked also!
});
该类的代码将遵循以下行:
export class AlertCollection {
constructor() {
}
// poll the data sources for alert data; store a promise that resolves
// to an array of alerts
poll() {
return this.pollTeapot()
.then(filteredAlerts)
.then(pollDeliverance);
}
// return a promise that fulfils to an array of the alerts you want
filteredAlerts(alerts) {
return alerts; // not filtering for now
}
// return a promise that fulfills to the initial array of alerts
pollTeapot() {
let process = (json) => {
json2 = JSON.parse(json);
return json2.map( (a) => new Alert(a) );
};
message = new MessageHandler("teapot", "alerts")
return message.request().then(process);
}
// Modify the alerts based on the response from Deliverance.
// (But for the time being let's not, and say we did.)
pollDeliverance(alerts) {
return alerts;
}
}
一些注释
filteredAlerts
可以执行任何您喜欢的操作,只要它返回一个结果数组
pollDeliverance
还可以执行任何您喜欢的操作—如果它需要调用另一个异步方法,请记住返回一个承诺,该承诺将解析为一组警报—可能会根据异步调用的结果进行更新
我创建了一个JSFIDLE来演示这一点——使用一个简单的getJSON
调用来复制其中一些的异步特性。正如我所提到的,这是一个复杂的过程,但它演示了以下过程:
活生生的例子:我不确定我是否完全理解了您的问题,但我将尝试为您提供一个通用的解决方案,一个接一个地链接承诺
someAsyncFunction().then(dataFromAsync1 => {
return anotherAsyncFunction(dataFromAsync1).then(dataFromAsync2 => {
return doSomethingWithData(dataFromAsync1, dataFromAsync2);
});
});
我大体上了解你的问题,但是你的头衔会议处理了2个承诺,我看不出这是在哪里-因为你只是在处理一个-message.request()
bit如果你想连锁承诺,你应该看看ES6中的Promise.all()
。@jamice inpoll()
我在连锁pollTeapot())
然后pollDeliverance()
;你是对的,目前后者没有做任何事情,但是如果我不能让它为其中一个工作,那么添加另一个也没有多大意义…@AndyJones啊,我看到pollDeliverance
发出另一个异步调用并更新Alert
的?@Hinrich——如果我理解正确,Promise.all()
是否会同时调用这两种服务?我不想这样。你需要记住从内部的回调中返回,然后
否则你将无法将事情链接到这里的问题是,我需要能够多次调用filteredAlerts()
以对返回的结果进行不同的筛选。我不想每次都要轮询数据源。这就是为什么我想要一个有自己状态的类;如果没有这些,我真的不认为上课有多大意义。@AndyJones那是我的错误,我应该改变论点,从你的原始答案返回(见更新的答案)。基本上,参数是警报
实例,您可以按自己喜欢的方式筛选并返回该数组。看看我的例子,我确实做到了这一点。听起来好像你在说,我不能让一个班级只进行一次民意调查,就可以多次兑现承诺。这是一个极大的限制。(我的想法是存储承诺,而不是实际结果。)@AndyJones我不确定我是否遵守。您当然可以缓存承诺的结果,但不要期望它在异步解决之前就存在。无论如何,在这里,你将非常接近于一个最受欢迎的dupe close问题,这是一个很难回答的问题,而且相当复杂。如果你想的话,请随时与我聊天!(只是出去吃午饭,所以可能在20分钟内没有反应)