实例创建时的异步操作

Async operations when instance created

我昨天参加了一个工作面试,我得到了如下编码挑战:

// 3. Coding challenge.
// The goal is to make function1/function2 to work only when the constructor has finished its async operations.
// You CAN'T change the notifyUrls function. Imagine it's a 3th party library you don't have control on.

// CAN'T CHANGE THIS.
//===================
function notifyUrls(item, callback) {
    asyncOperation(item).then((res) => {
        callback(res);
    });
}
//===================

 const asyncOperation = () => { return new Promise((resolve, reject) => { setTimeout(() => { console.log('Timeout execute'); resolve(); }, 2000); }); };

const URL1 = 'http://www.somerestapi/get1';
const URL2 = 'http://www.somerestapi/get2';
const URL3 = 'http://www.somerestapi/get3';

class MyClass {

    constructor() {
        [URL1, URL2, URL3].forEach(item => {
            notifyUrls(item, () => { });
        });
    }

    myFunction1() {
        // Only start working when constructor finished notifying.
        // ...
        console.log('myFunction1');
    }

    myFunction2() {
        // Only start working when constructor finished notifying.
        // ...
        console.log('myFunction2');
    }
}

这是我所做的:

// CAN'T CHANGE THIS.
//===================
function notifyUrls(item, callback) {
    asyncOperation(item).then((res) => {
        callback(res);
    });
}
//===================

 const asyncOperation = () => { return new Promise((resolve, reject) => { setTimeout(() => { console.log('Timeout execute'); resolve(); }, 2000); }); };

const URL1 = 'http://www.somerestapi/get1';
const URL2 = 'http://www.somerestapi/get2';
const URL3 = 'http://www.somerestapi/get3';

class MyClass {

    constructor() {
        this.ready = Promise.all([URL1, URL2, URL3].map((url) => { this.myAsyncCall(url); }));
    }

    myAsyncCall(item) {
        return new Promise((resolve, reject) => {
            notifyUrls(item, (res) => { resolve(res); });
        });
    }

    async myFunction1() {
        if (await this.ready) {
            // Only start working when constructor finished notifying.
            // ...
            console.log('myFunction1');
        }
    }

    myFunction2() {
        // Only start working when constructor finished notifying.
        // ...
        console.log('myFunction2');
    }
}

(async () => {
    const myClass = new MyClass();
    await myClass.myFunction1();
})();

但输出是:

myFunction1
Timeout execute
Timeout execute
Timeout execute

我想要的输出是:

Timeout execute
Timeout execute
Timeout execute
myFunction1

我该如何解决? 谢谢

问题在

    this.ready = Promise.all([URL1, URL2, URL3].map((url) => { this.myAsyncCall(url); }));

你的地图回调没有return任何东西

要么

    this.ready = Promise.all([URL1, URL2, URL3].map((url) => { return this.myAsyncCall(url); }));

    this.ready = Promise.all([URL1, URL2, URL3].map((url) =>  this.myAsyncCall(url)));

添加一些编码技巧

        notifyUrls(item, (res) => {
            resolve(res);
        });

可以简单地

        notifyUrls(item, resolve);

const asyncOperation = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve();
        }, 2000);
    });
};

只是

const asyncOperation = () => new Promise(resolve => setTimeout(resolve, 2000));