骄阳

三种方式理解Promises

骄阳 · 2016-11-20翻译 · 1392阅读 原文链接

这篇博文用三种方式来理解 Promises.

这里asyncFunc()是一个调用基于Promise函数的示例:

 function asyncFunc() {
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve('DONE'), 100);
        });
    }
    asyncFunc()
    .then(x => console.log('Result: '+x));

    // Output:
    // Result: DONE

那么什么是Promise呢?

  • 从概念上讲,调用 asyncFunc() 是一个阻塞函数的调用.

  • Promise 同时是一个值和一个事件触发器的容器.

从概念上: 调用一个基于Promise的函数是阻塞的

 function asyncFunc() {
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve('DONE'), 100);
        });
    }
    async function main() {
        const x = await asyncFunc(); // (A)
        console.log('Result: '+x);

        // Same as:
        // asyncFunc()
        // .then(x => console.log('Result: '+x));
    }
    main();

main()一个异步函数. 它的函数体很好地从 概念上 表达发生了什么 - 我们通常如何看待异步计算:

  • 行 (A): 等待,直到 asyncFunc() 完成.

  • 行 (B): 之后打印它的结果 x.

在ECMAScript 6 和 generators 之前,不能挂起和继续代码,这是为什么,对于Promises,要把代码恢复后发生的一切放进回调函数里. 调用该回调函数与继续代码相同.

Promise 是一个异步传值的容器

如果一个函数返回Promise, 那么这个Promise就像一片空白,函数一旦计算完,将(通常)最终填充其结果。你可以通过一个数组模拟这个过程的一个简单版本:

 function asyncFunc() {
        const blank = [];
        setTimeout(() => blank.push('DONE'), 100);
        return blank;
    }
    const blank = asyncFunc();
    // Wait until the value has been filled in
    setTimeout(() => {
        const x = blank[0]; // (A)
        console.log('Result: '+x);
    }, 200);

使用Promises, 不必通过[0]访问最终值(如行(A)),可以使用then()方法和回调函数。

Promise 是一个事件触发器

另一种查看Promise的方法是作为一个触发事件的对象。

 function asyncFunc() {
        const eventEmitter = { success: [] };
        setTimeout(() => { // (A)
            for (const handler of eventEmitter.success) {
                handler('DONE');
            }
        }, 100);
        return eventEmitter;
    }
    asyncFunc()
    .success.push(x => console.log('Result: '+x)); // (B)

注册事件监听器(行(B))可以调用 asyncFunc()后完成,因为这段代码完成后,被传递给setTimeout() (行(A))的回调函数是异步执行的。

正常的事件触发器专门提供多个事件,一旦注册就开始执行。

相比之下,Promises专门提供一个值,并提供内置保护以防注册太晚:Promise的结果被缓存并传递给被注册后的事件监听器。

延展阅读

相关文章