简体   繁体   中英

Why await a promise doesn't wait the promise to resolve?

I am trying to learn to use properly async await but I am kind of cofused about it.

In the snippets, I am trying to build an array of object containing the infos I need about the file I am uploading in the component. The problem is that the objects in this.fileInfo are not exactly waiting the promise to return the encoded images, returning this output as I console.log this.fileInfo:

输出

As you can see, the key image is a ZoneAwarePromise whose value is undefined. Can you please help me to fix this?

Function build()

async build(e) {
    let files = e.target.files;
    this.j = Array.from(files);
    this.fileInfo = await this.j.reduce((acc, cur) => [
        ...acc, {
            name: cur.name.replace(/^.*\\/, ""),
            sizeunit: this.getSize(cur.size),
            extention: cur.name.split(/\.(?=[^\.]+$)/).slice(-1).pop().toString(),
            image: this.previewFile(cur)
        }
    ], [])
    console.log(await this.fileInfo);
}

Promise

async previewFile(file) {

    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => {
        return new Promise((res) => {
            res(reader.result)
        }).then( res => res);
    };
}

You are not awaiting anything in this function: async previewFile(file) . Perhaps you assume returning a new Promise somewhere along the lines of your code will make it function as a Promise. In this particular case it will not work, because it is inside a delegate (onload), that will not be executed within the scope of your function previewFile() .

You can lose the async modifier, because you can return a Promise instead:

previewFileAsync(file) {
    // the async modifier keyword is not necessary,
    // because we don't need to await anything.
    return new Promise((res) => {
         const reader = new FileReader();
         reader.readAsDataURL(file);
         reader.onload = () => res(reader.result);
    });
}

When you call this, you can await it inside your loop:

async buildAsync(e) {
    let files = e.target.files;
    for(let i = 0; i < files.length; i++) {
        const file = files[i];
        const preview = await previewFileAsync(file);
        // Do something with preview here...
    }
}

Of course, you can execute a range of promises to allow for some sort of concurrency, but this will help get you started.

I added the Async suffix to your method so a caller knows that this can be awaited. It does not do anything special, but it helps clarify your code. You can use whatever suffix you think is right. I'm just used to the Async suffix.

Edit

Stackblitz example of async logic

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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