js使用promise保证函数内部语句的顺序执行[函数返回promise对象]

简单的使用场景

Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。
JavaScript有一个基于事件循环的并发模型,事件循环负责执行代码、收集和处理事件以及执行队列中的子任务。这个模型与其它语言中的模型截然不同,比如 C 和 Java。[2]
(在本轮 事件循环 运行完成之前,回调函数是不会被调用的。)
比如:

function t(){
    
    
    return Promise.resolve('aaa')
            .then(data => {
    
     console.log("then1: ", data); })
            .then(data => {
    
     console.log("then2: ", data); return 'bbb'; })
            .then(data => {
    
     console.log("then3: ", data); return Promise.resolve('ccc'); })
            .catch(err => {
    
     console.log("eee"); return Promise.reject('eee'); });
}


function main(){
    
    
    console.log("main start");
    t()
        .then(data => {
    
     console.log("333: ", data); })
        .catch(err => {
    
     console.log("eee"); return 'ggg'});
    console.log("main end");
}

main();

其实际输出如下:

$ node a.js
main start
main end
then1:  aaa
then2:  undefined
then3:  bbb
333:  ccc

但是实际上我们想让t()做完再输出main end,那么我们用一下promise的then就可以了:

function t(){
    
    
    return Promise.resolve('aaa')
            .then(data => {
    
     console.log("then1: ", data); })
            .then(data => {
    
     console.log("then2: ", data); return 'bbb'; })
            .then(data => {
    
     console.log("then3: ", data); return Promise.resolve('ccc'); })
            .catch(err => {
    
     console.log("eee"); return Promise.reject('eee'); });
}


function main(){
    
    
    console.log("main start");
    t()
        .then(data => {
    
     console.log("333: ", data); })
        .then(
            data => {
    
    console.log("main end");}
        );
}
main();

那么输出变为:

$ node a.js
main start
then1:  aaa
then2:  undefined
then3:  bbb
333:  ccc
main end

实际用例

# 1 这是被调用的函数
    public add(
        options: IGroundVechicleOptions = {
    
    }
    ) {
    
    
... <此处被作者省略>
        // make sampledPositions clampToGround
        let addedPromise = sampleTerrainMostDetailed(
            this._viewer!.terrainProvider,
            sampledPositions
        ).then(() => {
    
    
... <此处被作者省略>
... <处理数据>
            console.log("end adding vehicle with id: ", vehicleID, " is added!", this._showFlags.keys());
        });
        return addedPromise;
    }

我们的目标是让add里的

console.log("end adding vehicle with id: “, vehicleID, " is added!”, this._showFlags.keys());

这一句输出完成再执行:

this.groundVehicle.getIDs();

具体做法如下:

# 2 调用上面的函数
    public initGroundVehicle() {
    
    
        // init the ground Vehicle
        this.groundVehicle = new _GV(<Viewer>this.cmap.viewer);
        this.groundVehicle.add(options)
        .then(ids => {
    
    
            console.log("promise resolved!");
            // update the vehicle id list
...<获取处理好的数据>
            this.vehicleIDList = this.groundVehicle.getIDs();
        }, () => {
    
    
             // reject func, do nothing
        })
        .then(tmp1 => {
    
    
            console.log("tmp1 nothing!");
        })
        .then(tmp2 => {
    
    
            console.log("tmp2 nothing!");
        });
    }

其实上面最关键的步骤在于add函数的返回值:

return addedPromise;

返回的是一个新的promise,这个promise承诺的是之前的回调函数的完成。具体请看[1]中的链式调用。

使用 Promise 时,会有以下约定[1]:

  • 1 在本轮 事件循环 运行完成之前,回调函数是不会被调用的。
  • 2 即使异步操作已经完成(成功或失败),在这之后通过 then() 添加的回调函数也会被调用。
  • 3 通过多次调用 then() 可以添加多个回调函数,它们会按照插入顺序进行执行。
    Promise 很棒的一点就是链式调用(chaining)。

Refer

Guess you like

Origin blog.csdn.net/cxy_hust/article/details/113620780