我无法解决这个问题。 我如何等待i == 2完成再继续其他我的工作?
class Observable {
constructor() {
this.observers = [];
}
subscribe(f) {
this.observers.push(f);
}
unsubscribe(f) {
this.observers = this.observers.filter(subscriber => subscriber !== f);
}
notify(data, options) {
this.observers.forEach(observer => observer(data));
}
}
let myObserver = new Observable();
for (let i=0; i <= 2; i++){
let proc = async function processor(foo) {
console.log('Processing ' + i + ' ' + foo);
if (i != 2){
//await for i = 2 to finish
//??? <----
}
// do other stuff which requires i = 2
await new Promise(r => setTimeout(r, i * 1000));
console.log('Done ' + i);
}
myObserver.subscribe(proc);
}
myObserver.notify('Hello');
我添加了一个更具体的示例-可能会阐明我实际尝试实现的目标。 (使用与上述相同的Observable类)
let allData = {};
let dataProviders = {
provderA: {
url: 'http://provder.a.com',
observer: new Observable(),
requires: null
},
providerB: {
url: 'http://provder.b.com',
observer: new Observable(),
requires: 'providerA'
}
}
let consumers = {
consumerX: {
provider: 'providerA'
},
consumerY: {
provider: 'providerB'
},
consumerZ: {
provider: 'providerB'
}
}
function getData(providerName) {
let urlParam = '';
if (dataProviders[providerName][requires] != null) {
// (a)wait for providerA / dataProviders[providerName][requires]
// ??? <----
urlParam += allData[dataProviders[providerName][requires]]['parameter']
}
$.getJSON(dataProviders[providerName][url] + urlParam).done(function (result) {
allData[providerName] = result;
dataProviders[providerName][observer].notify(allData)
});
}
for (const consumer of Object.keys(consumers)) {
let subscription = function (data) {
console.log('process data');
console.log(data)
}
dataProviders[consumers[consumer]['provider']].subscribe(subscription);
}
for (const providerName of Object.keys(dataProviders)) {
getData(providerName);
}
答案 0 :(得分:2)
我怀疑您正在寻找
async function getData(providerName) {
const { url, requires } = dataProviders[providerName];
let urlParam = '';
if (requires != null) {
const requiredData = await new Promise(resolve => {
dataProviders[requires].observer.subscribe(() => {
resolve(allData[requires]);
});
// getData(requires); ???
});
urlParam += requiredData.parameter;
}
const result = await $.getJSON(url + urlParam);
allData[providerName] = result;
dataProviders[providerName][observer].notify(allData);
}
如果您未使用特定的resolve
而不是result
通知观察者,则可以简化allData
r回调的订阅。但是,如果您不多次获取数据,我想您可以完全放弃该Observer
类,而仅使用Promise。这样一来,您就可以摆脱allData
商店,而只需记住getData
返回的承诺,就可以大大简化整个代码:
const dataProviders = {
provderA: {
url: 'http://provder.a.com',
promise: null,
requires: null
},
providerB: {
url: 'http://provder.b.com',
promise: null,
requires: 'providerA'
}
};
function getDataOnce(providerName) {
const provider = dataProviders[providerName];
if (provider.promise == null)
provider.promise = getData(provider);
return provider.promise;
}
async function getData({ url, requires }) {
let urlParam = '';
if (requires != null) {
const requiredData = await getDataOnce(requires);
urlParam += requiredData.parameter;
}
const result = await $.getJSON(url + urlParam);
return result;
}
const consumers = {
consumerX: {
provider: 'providerA'
},
consumerY: {
provider: 'providerB'
},
consumerZ: {
provider: 'providerB'
}
};
for (const consumer of Object.values(consumers)) {
getDataOnce(consumer.provider).then(data =>
console.log('process data');
console.log(data)
});
}
答案 1 :(得分:0)
您可以在此处使用诺言。
async function getData(providerName) {
if (dataFromAnotherProviderIsNeeded) {
// wait till promise resolve
await new Promise( async (resolve) => {
await getData(anotherProvider);
// when request is done, resolve
resolve();
};
}
// Previous request is done
}
另一种选择是使用rxjs中的concat等到第一个请求发出之前,再执行第二个请求(使用rxjs功能更强大,但在简单情况下可能不需要)。