情诗网 >套路情话 > 正文

JavaScript:Promise的基础套路

来源:情诗网    2020-12-27    分类:套路情话

关于Promise的基本内容,已经写过一篇文章。基本的会用,偶尔也用过,不过知识点比较多,并且代码在外面套了好几层,感觉也比较复杂,一直理不顺头绪。最近看了下面链接的几篇文章,感觉很不错,对于Promise基本概念的理解比以前要清晰一点了。
Promise的知识点很多,这里是一次从多到少的收敛过程,写了几点平时可能会用到的最基础的用法。

大白话讲解Promise(一)
这篇文章写得还是比较简单直接的,对于理解概念很有帮助,推荐好好看看。

廖雪峰的Promise
这篇文章对于概念的分解还是比较详细的,很不错。里面的例子直接copy到chrome的控制台会报错,不过简单修改一下就可以了。本文的例子基本上都是从这里简单修改来的。

适用Promise的三种场景?

Promise和回调地狱是什么关系?

Promise的编程范式:面向对象 or 函数式?

Promise对异步调用的常用封装套路:

function promiseFunction(resolve, reject) {
    let timeOut = Math.random() * 2;
    let flag = (timeOut < 1);
    let callback = () => {
        if (flag) {
            console.log('success...');
            return resolve('data: 200 OK'); // 加个return是个好习惯
        } else {
            console.log('fail...');
            return reject('error: timeout in ' + timeOut + ' seconds.'); // 加个return是个好习惯
        }
    };
    // start process
    console.log('start async function ...');
    setTimeout(callback, (timeOut * 1000));
}

function asyncFunction () {
    let promise = new Promise(promiseFunction);
    return promise;
}

在实际使用中,可以写得简洁一些,上面的代码可以精简如下:

function asyncFunction () {
    return new Promise(function(resolve, reject) {
        let timeOut = Math.random() * 2;
        let flag = (timeOut < 1);
        // start process
        console.log('start async function ...');
        setTimeout(() => {
            if (flag) {
                console.log('success...');
               return  resolve('data: 200 OK'); // 加个return是个好习惯
            } else {
                console.log('fail...');
                return reject('error: timeout in ' + timeOut + ' seconds.'); // 加个return是个好习惯
            }
        }, (timeOut * 1000));
    });
}

Promise简单使用的套路:

then函数中一般不建议放异步过程,这样做会增加理解的难度。下面这篇文章中就有这样的例子:
Promise.prototype.then()

asyncFunction().then((data) => {
    console.log(data);
    return data; // 把数据往下传,是个好习惯
    }).catch((error) => {
    console.log(error);
});

场景1: 级联调用使用的套路:

下面这个例子,就是先用Promise包装了一个异步过程,(乘10的函数);以及一个同步过程,(加100的函数);用随机数的方式,模拟过程失败的情况。然后通过then函数级联的方式定义依赖过程。最后用catch捕捉过程中遇到的错误。

Step1:用Promise封装过程

// input*10的计算结果; setTimeout模拟异步过程;
function multiply10(input) {
    return new Promise(function (resolve, reject) {
        let temp = Math.random() * 1.2;
        let flag = (temp < 1);
        console.log('calculating ' + input + ' x ' + 10 + '...');
        setTimeout(() => {
            if (flag) {
                return resolve(input * 10);
            } else {
                return reject('multiply error:' + temp);
            }
        }, 500);
    });
}

// input+100的计算结果;同步过程
function add100(input) {
    return new Promise(function (resolve, reject) {
        let temp = Math.random() * 1.2;
        let flag = (temp < 1);
        console.log('calculating ' + input + ' + ' + 100 + '...');
        if (flag) {
            return resolve(input + 100);
        } else {
            return reject('add error:' + temp);
        }
    });
}

Step2:用then函数级联的方式定义依赖过程:

// 结果是3300,或者报错
Promise.resolve(32).then(multiply10).then(multiply10).then(add100).then(data => {
    console.log('Got value: ' + data);
    return data;
}).catch(error => {
    console.log(error);
});

// 结果是1160,或者报错
Promise.resolve(6).then(add100).then(multiply10).then(add100).then(data => {
    console.log('Got value: ' + data);
    return data;
}).catch(error => {
    console.log(error);
});

// ... ... 还能写出很多的组合情况

一个then用来执行同步的回调函数。这里要注意将要传递的data return出去,不然,整个链式调用参数传递会中断。

.then(data => { 
    callbacek(data);
    return data;   // 这里要把接收到的data传出去,不然整个调用链的参数传递会断掉。
})

一个then用来包装异步过程的,并把这个新建的Promise return出去,形成异步过程依赖链。

.then(data => { 
    return new Promise(function(resolve, reject) {
        let flag = ((Math.random() * 2) < 1);  // demo flag
        let newData = data + 1; // demo data 
        setTimeout(() => { // demo async function
            if (flag) {
                resolve(newData);
            } else {
                reject(new Error('error message'));
            }
        }, 10);
    });
})
// 结果是9880,或者报错
Promise.resolve(888).then(add100).then(data => {
    console.log('add100之后的结果为:' + data);
    return data;
}).then(multiply10).then(data => {
    console.log('multiply10之后的结果为:' + data);
    return data;
}).then(data => {
    console.log('Got value: ' + data);
    return data; // 这里是最后了,不return data对流程没影响。不过谁知道以后会不会加新的节点,return一下还是好的。
}).catch(error => {
    console.log(error);
});

场景2: 几个异步回调都成功,然后再进行下一步操作
场景3: 几个异步回调,只要有一个成功,就可以进行下一步

function asyncFunction1(data = null) {
    return new Promise(function(resolve, reject) {
        let temp = Math.random() * 2;
        let flag = (temp < 1);
        // start process
        console.log('start asyncfunction1 ...');
        setTimeout(() => {
            if (flag) {
                if (data) {
                    return resolve(data);
                } else {
                    return resolve('success: asyncfunction1===');
                }
            } else {
                return reject(`fail:asyncfunction1; temp:${temp}`);
            }
        }, 500);
    });
}

function asyncFunction2(data = null) {
    return new Promise(function(resolve, reject) {
        let temp = Math.random() * 2;
        let flag = (temp < 1);
        // start process
        console.log('start asyncfunction2 ...');
        setTimeout(() => {
            if (flag) {
                if (!data) {
                    return resolve(data);
                } else {
                    return resolve('success: asyncfunction2');
                }
            } else {
                return reject(`fail:asyncfunction2; temp:${temp}`);
            }
        }, 500);
    });
}

// 这里传过来的是成功结果的数组
Promise.all([asyncFunction1(), asyncFunction2()]).then(array => {
    console.log(JSON.stringify(array));
    return array; // 这里传递的是数组,比较特殊
}).catch(error => {
    console.log(error);
});

// 结果是success: asyncfunction1;跑得比较快
Promise.race([asyncFunction1(), asyncFunction2()]).then(data => {
    console.log(data);
    return data;
}).catch(error => {
    console.log(error);
});

done、finally、success、fail等其他内容呢?

Promise 对象(阮一峰)

JavaScript Promise迷你书(中文版)

Promise MDN

热门文章