繁体   English   中英

在 function 内等待/观察

[英]await / observe within function

我无法理解这一点。 如何等待 i==2 完成,然后再继续其他 i?

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 class)

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);
}

我怀疑你正在寻找

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);
}

如果您没有向观察者通知具体result ,而不是allData ,则可以简化resolve r 回调的订阅。 但是,我想您可以完全放弃Observer class 并使用 promise 代替,如果您不多次获取数据。 这将允许您摆脱allData存储,只需记住getData返回的 promise ,从而大大简化整个代码:

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)
    });
}

您可以在此处使用 promise。

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 功能更强大,但在简单的情况下可能不需要)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM