深入探究Promise构造函数

  • Post author:
  • Post category:其他




原理

// promise 承诺   
// 1. 实现承诺  resolve (解决问题) 
// 2. 石沉大海  reject (拒绝接收)
// 3. 等待...   pending (苦苦等待...)
// promise:解决异步(互不相干你做你的我做我的互不阻塞互不等待)流程化的一种手段  
// 同步:A任务结束出结果,B任务拿到A任务的结果才执行下面的任务

// Promise 构造函数 需要new
// Promise 参数(有且仅有一个) excutor 执行器
// excutor => resolve  reject 函数
// excutor 在 new Promise 时抵用

// excutor 是同步执行的
let promise = new Promise((resolve, reject) => {
    // console.log(1);
    // resolve('承诺实现');
    reject('承诺石沉大海');
    // throw new Error('Error: 承诺石沉大海');// 手动抛出错误 和reject一样的
});
// console.log(2);  // 先打印1  在打印2

// 说明then是异步调用
// promise.then((res) => {
//     console.log('then');
//     console.log(res);
// }, (err) => {
//     console.log(err);
// })
promise.then((res) => {
    console.log('then');
    console.log(res);
}).catch(err => {
    console.log(err);
})

console.log('Global'); // 先打印Global 在打印then

// err在第一个then没有处理,具有穿透性,下个then处理也是有结果的,
// 没有处理err的话,有catch就走catch
promise.then((res) => {
    console.log('then');
}).then(() => {

}).then(()=>{

}, (err) => {
    console.log(err)
})

// promise.then((res) => {
//     console.log('aa');
//     return new Promise((resolve, reject) => resolve('成功'))
// }).then((res) => {
//     console.log(res);
// })



了解一下回调地狱

// 高阶函数:函数参数里面有函数,闭包返回一个函数

// function doSth (t, cb) {
//     return function () {
//         if (--t === 0) {
//             cb();
//         }
//     }
// }

function logSth (cb) {
    console.log('aaaaaaaaaa');
    cb();
}

function logSth2 (cb) {
    console.log('bbbbbbbbb');
    cb();
}
function logSth3 () {
    console.log('cccccccccc');
}

// let fn = doSth(4, logSth.bind(null, logSth2));

// 回调地狱
function doSth (t) {
    return function () { 
        if ( --t === 0 ) {
            logSth(function () {  
                logSth2(function () {  
                    logSth3()
                })
            })
        }
    }
}

let fn = doSth(4, logSth)

fn();
fn();
fn();
fn(); // aaaaaaaaaaa



结合node.js(fs.readFile)使用promise

const fs = require('fs');
let uid = 3;
fs.readFile('./data/user.json', 'utf8', function (err, data) {
    const userData = JSON.parse(data),
        userInfo = userData.filter(item => item.id === uid)[0];

    fs.readFile('./data/userCourse.json', 'utf8', function (err, data) {
        const userCourseData = JSON.parse(data),
            userId = userInfo.id,
            userCourse = userCourseData.filter(item => {
                return item.uid === userId
            })[0];
            
        fs.readFile('./data/course.json', 'utf8', function (err, data) {
            const courseData = JSON.parse(data),
                userCourses = userCourse.courses;

            let _arr = [];
            userCourses.map(id => {
                courseData.map((item) => {
                    if (item.id) {
                        _arr.push(item);
                    }
                })
            });

            const userCourseInfo = {
                username: userInfo.username,
                cuerses: _arr
            }

            fs.writeFileSync(`./data/${userInfo.username}.json`, JSON.stringify(userCourseInfo))
        });


    })

})
const fs = require('fs');

let uid = 1;

function readFile (path, prevData) {
    return new Promise((resolve, reject) => {
        fs.readFile(path, 'utf8', function (err, data) {
            if (err) {
                reject(err);
            }

            const resData = JSON.parse(data);
            resolve({
                prevData,
                resData
            })
        })
    })
}

readFile('./data/user.json')
    .then((res)=>{
        const { resData } = res,
            userInfo = resData.filter(item => item.id === uid)[0];
        
        return readFile('./data/userCourse.json', userInfo);
    })
    .then((res) => {
        const { prevData, resData } = res,
            userId = prevData.id,
            userCourse = resData.filter(item => item.uid === userId)[0];
       
        return readFile('./data/course.json',{
            username: prevData.username,
            userCourse
        })
    })
    .then((res) => {
        const { prevData, resData } = res,
              userCourses = prevData.userCourse.courses;
        
        let _arr = [];
        userCourses.map(id => {
            resData.map(item => {
                if (item.id === id) {
                    _arr.push(item);
                }
            })
        });

        const userCourseInfo = {
            username: prevData.username,
            courses: _arr
        }

        fs.writeFileSync(`./data/${userCourseInfo.username}.json`, JSON.stringify(userCourseInfo));
    })
    .catch((err) => {
        console.log(err);
    })



promise解决异步并发的问题

Promise.all()

const fs = require('fs');

var num= 1;

function readFile(path, isSetError) {
    return new Promise((resolve, reject) => {
        fs.readFile(path, 'utf8', function (err, data) {
            if (err || isSetError) {
                reject('承诺石沉大海了~~~~~'+ num ++);
            }

            const resData = JSON.parse(data);
            resolve(resData);
        })
    })
}

readFile('./data/user.json').then((res) => {
    console.log(res);

    // return Promise.resolve("成功"); //和下面写法是一样的
    return Promise.reject("失败"); //和下面写法是一样的
    // return new Promise((resolve,reject) => {resolve("成功")}); 
}).then((res) => {
    console.log(res); // 成功
},(err) => { //当为reject时走then(不管有没有catch)
    console.log("then" + err); // then失败
}
).catch((err) =>{ //当为reject时then没有err走catch
    console.log("catch" + err); // catch失败
})

// readFile('./data/user.json').then((res) => {
//     console.log(res);
// })
// readFile('./data/userCourse.json').then((res) => {
//     console.log(res);
// })
// readFile('./data/course.json').then((res) => {
//     console.log(res); 
// })

// 合并三个文件内部的内容为一个数组 并且 按照顺序排列 如果一个读取失败, 就让这个数组返回rejected(失败状态)
// 接收interable(可迭代的对象)类型的数据 => Array Set Map
// Promise.all([
//     readFile('./data/user.json'),
//     readFile('./data/userCourse.json', true),
//     readFile('./data/course.json')
// ]).then((res) => {
//     console.log(res);
// }).catch((err) => {
//     console.log(err);
// })

// 用多个异步任务并发运行,他的结果创建承诺之后使用,等待所有任务结果的完成
// interable内部元素传递的是promise对象集合,如果不是promise,直接resolve Promise.resolve(0 || '123' || true)
// interable内部没有元素,返回空数组;
// 有一个promise是rejected  实例回调rejected
// 失败原因是第一个失败的promise结果



Promise.race可以测试请求的速度

Promise.race()

const fs = require('fs');

function readFile (path, isSetError) {
    return new Promise ((resolve, reject) => {
        fs.readFile(path, "utf8", function(err, data) {
            if (err || isSetError) {
                reject('承诺石沉大海....')
            }

            const resData = JSON.parse(data);
            resolve(resData);
        })
    })
}

Promise.race([
    // readFile('./data/user.json', true),
    // readFile('./data/userCourse.json'),
    // readFile('./data/course.json')
])
.then((res) => {
    console.log(res);
})
.catch((err) => {
    console.log(err);
})
// 谁先完成就返回哪个promise结果,无论是fullfilled(完全完成)还是rejected(失败)
// 如果可迭代容器为空的话,就返回的promise为pending (等待的状态)
// 可以用来资源或者接口的响应速度
function getImg () {
            return new Promise((resolve, reject) => {
                const oImg = new Image();

                oImg.onload = function () {
                    resolve(oImg);
                }

                oImg.src = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1604564434152&di=f115b9bbe7f8763e6a3e83a131f46b27&imgtype=0&src=http%3A%2F%2Fgss0.baidu.com%2F-Po3dSag_xI4khGko9WTAnF6hhy%2Fzhidao%2Fpic%2Fitem%2F728da9773912b31b2b0d907a8018367adab4e104.jpg';

            })
        }

        function timeout () {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    reject('图片请求超时');
                }, 100)
            })
        }

        Promise.race([
            getImg(),
            timeout()
        ])
        .then((res) => {
            console.log(res);
        })
        .catch((err) =>{
            console.log(err);
        })



Promise文档解读

MyPromise.js文件:

const Pending = 'Pending',
    FulFilled = 'FulFilled',
    Rejected = 'Rejected';

function resolvePromise(promise2, x, resolve, reject) {
    if (promise2 === x) {
        return reject(new TypeError('Chaining cycle detected for promise #<MyPromise>'));
    }
    let called = false;
    if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
        try {
            let then = x.then; // throw Error
            if (typeof then === 'function') { // 认定为Promise
                then.call(x, (y) => {
                    if (called) return;
                    called = true;
                    resolvePromise(promise2, y, resolve, reject);
                }, (r) => {
                    if (called) return;
                    called = true;
                    reject(r);
                })
            } else {
                resolve(x);
            }
        } catch (e) {
            if (called) return;
            called = true;
            reject(e);
        }
    } else {
        resolve(x);
    }
}


class MyPromise {
    constructor(executor) {
        this.status = Pending;
        this.value = undefined;
        this.reason = undefined;

        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];

        const resolve = (value) => {
            if (this.status === Pending) {
                this.status = FulFilled;
                this.value = value;
                // 发布
                this.onFulfilledCallbacks.forEach(fn => fn());
            }
        }
        const reject = (reason) => {
            if (this.status === Pending) {
                this.status = Rejected;
                this.reason = reason;
                // 发布
                this.onRejectedCallbacks.forEach(fn => fn());
            }
        }

        // 捕获异常
        try {
            executor(resolve, reject);
        } catch (e) {
            reject(e);
        }
    }

    // x 可能是普通值 或者 promise
    then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
        onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason};
        
        let promise2 = new MyPromise((resolve, reject) => {
            if (this.status === FulFilled) {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e)
                    }
                }, 0);
            } else if (this.status === Rejected) {
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e)
                    }
                }, 0);
            } else if (this.status === Pending) {
                // 订阅的过程
                this.onFulfilledCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onFulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            console.log(e);
                            reject(e);
                        }
                    }, 0);
                });
                this.onRejectedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onRejected(this.reason);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e)
                        }
                    }, 0);
                })
            }
        });
        return promise2;
    }

    catch (errCallback) {
        return this.then(null, errCallback);
    }


}

// common.js模块导出
module.exports = MyPromise;

index.js文件

const MyPromise = require('./MyPromise');

let promise1 = new MyPromise((resolve, reject) => {
    resolve('promise1');
    // reject('Error');
})
let promise2 = promise1.then((value) => {
    // return new Error('Error');
    // return Promise.resolve('Promise resolve');
    return new MyPromise((resolve, reject) => {
        setTimeout(() => {
            resolve(new MyPromise((resolve, reject) => {
                resolve(new MyPromise((resolve, reject) => {
                    resolve('new Promise resolve')
                }));
            }));
        }, 2000);
    });
}, (reason) => {
    return reason;
});

promise2.then().then().then().then().then((value) => {
    // console.log('fulfilled: ' + value);
    throw Error('Error');
}, (reason) => {
    console.log('rejected: ' + reason);
})
.catch((e) => {
    console.log(e);
})



版权声明:本文为beLaity原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。