Promise笔记

执行流程

执行流程

// Promise的设计

new Promise(
    /* 执行器 executor */
    function (resolve, reject) {
        // 一段耗时很长的异步操作
        resolve(); // 数据处理完成
        reject(); // 数据处理出错
    }
)
    .then(function A() {
        // 成功,下一步
    }, function B() {
        // 失败,做相应处理
    });

支持情况

支持情况

三个状态

  • pending[待定] 初始状态
  • fulfilled[实现] 操作成功
  • rejected[被否定] 操作失败

Promise 状态一经改变,不会再边
Promise 一经创建,执行器立即执行

.then()

  • 接受两个函数作为参数fulfilled,rejexted
  • 返回一个新的Promise实例,所以可以链式调用
  • 当前边的Promise状态改变时,·then()根据其最终的状态,选择待定状态相应函数执行
  • 状态相应函数可以返回新的Promise或其他值
  • 如果返回新的Promise,那么下一级的.then()会在新的Promise状态改变后执行
  • 如果返回其他值,则会立即执行下一级的.then()

基础例子

定时执行

new Promise( resolve => {
    setTimeout( () => {
        resolve('hello');
    }, 2000);
})
    .then( value => {
        console.log( value + ' world');
    });

输出 : hello world

分两次,顺序依次执行

new Promise(resolve => {
        setTimeout(() => {
            resolve('hello');
        }, 2000);
    })
    .then(value => {
        console.log(value);
        return new Promise(resolve => {
            setTimeout(() => {
                resolve('world1');
            }, 2000);
        });
    })
    .then(value => {
        console.log(value + ' world2');
    });

输出
hello
world1 world2

假如一个Promise已经完成了,再.then()会怎样?

let promise = new Promise(resolve => {
    setTimeout(() => {
        console.log('the promise fulfilled');
        resolve('hello, world');
    }, 1000);
});

setTimeout(() => {
    promise.then( value => {
        console.log(value);
    });
}, 3000);

输出
the promise fulfilled
hello, world

假如在.then()的函数里面不返回新的Promise,会怎样?

new Promise(resolve => {
    setTimeout( () => {
        resolve('hello');
    }, 2000);
})
    .then( value => {
        console.log(value);
        (function () {
            return new Promise(resolve => {
                setTimeout(() => {
                    console.log('Mr.Laurence');
                    resolve('Merry Xmas');
                }, 2000);
            });
        }());
        return false;
    })
    .then( value => {
        console.log(value + ' world');
    });

输出
hello
false world
Mr.Laurence

嵌套.then()

new Promise(resolve => {
        console.log('Step 1');
        setTimeout(() => {
            resolve(100);
        }, 1000);
    })
    .then(value => {
        return new Promise(resolve => {
                console.log('Step 1-1');
                setTimeout(() => {
                    resolve(110);
                }, 1000);
            })
            .then(value => {
                console.log('Step 1-2');
                return value;
            })
            .then(value => {
                console.log('Step 1-3');
                return value;
            });
    })
    .then(value => {
        console.log(value);
        console.log('Step 2');
    });

//改写

new Promise(resolve => {
        console.log('Step 1');
        setTimeout(() => {
            resolve(100);
        }, 1000);
    })
    .then(value => {
        return new Promise(resolve => {
            console.log('Step 1-1');
            setTimeout(() => {
                resolve(110);
            }, 1000);
        })
    })
    .then(value => {
        console.log('Step 1-2');
        return value;
    })
    .then(value => {
        console.log('Step 1-3');
        return value;
    })
    .then(value => {
        console.log(value);
        console.log('Step 2');
    });

输出
Step 1
Step 1-1
Step 1-2
Step 1-3
110
Step 2

典型问题

假设doSomething和doSomethingElse返回的都是一个Promise实例

原文地址http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html
译文地址http://fex.baidu.com/blog/2015/07/we-have-a-problem-with-promises/



// 问题一
doSomething()
    .then(function () {
        return doSomethingElse();
    })
    .then(finalHandler);

// 答案
// doSomething
// |-----------|
//             doSomethingElse(undefined)
//             |------------|
//                          finalHandler(resultOfDoSomethingElse)
//                          |------------|


// 问题二
doSomething()
    .then(function () {
        doSomethingElse();
    })
    .then(finalHandler);

// 答案
// doSomething
// |------------------|
//                    doSomethingElse(undefined)
//                    |------------------|
//                    finalHandler(undefined)
//                    |------------------|


// 问题三
doSomething()
    .then(doSomethingElse())
    .then(finalHandler);

// 答案
// doSomething
// |------------------|
// doSomethingElse(undefined)
// |----------------------------------|
//                    finalHandler(resultOfDoSomething)
//                    |------------------|


// 问题四
doSomething()
    .then(doSomethingElse)
    .then(finalHandler);

// 答案
// doSomething
// |-----------|
//             doSomethingElse(resultOfDoSomething)
//             |------------|
//                         finalHandler(resultOfDoSomethingElse)
//                         |------------------|

实现队列

let promise = doSomething();

promise = promise.then(doSomethingElse);
promise = promise.then(doSomethingElse2);
promise = promise.then(doSomethingElse3);

使用forEach

function queue(things) {
    let promise = Promise.resolve();
    things.forEach(thing => {
        promise = promise.then(() => {
            return new Promise(resolve => {
                doThing(thing, () => {
                    resolve()
                });
            });
        });
    });
    return promise;
}

queue(['21lots', 'of', 'things']);

常见错误 : 没有把.then()产生的❤新Promise实例复制给Promise,没有生成队列

使用.reduce()

错误处理

  • reject('错误信息').then(null,message => {})
  • throw new Error('错误信息').catch(message => {})
  • 推荐使用第二种,清晰好读,并且可以捕获前面的错误
  • 建议在所有队列都加上.catch(),以避免漏掉错误处理造成意想不到的问题

Promise会自动捕获内部异常,并交给rejected响应函数处理-catch捕获

console.log('here we go');
new Promise( resolve => {
    setTimeout( () => {
        throw new Error('bye');
    }, 2000);
})
    .then( value => {
        console.log( value + ' world');
    })
    .catch( error => {
        console.log( 'Error:', error.message);
    });

Promise会自动捕获内部异常,并交给rejected响应函数处理-reject响应捕获

new Promise( (resolve, reject) => {
    setTimeout( () => {
        reject('bye');
    }, 2000);
})
    .then( value => {
        console.log( value + ' world');
    }, value => {
        console.log( 'Error:', value);
    });

.catch() + .then() 连用

new Promise(resolve => {
    setTimeout(() => {
        resolve();
    }, 1000);
})
    .then( () => {
        console.log('start');
        throw new Error('test error');
    })
    .catch( err => {
        console.log('I catch:', err);

        // 下面这一行的注释将引发不同的走向
        // throw new Error('another error');
    })
    .then( () => {
        console.log('arrive here');
    })
    .then( () => {
        console.log('... and here');
    })
    .catch( err => {
        console.log('No, I catch:', err);
    });

Promise.all()

  • Promise.all([p1,p2,p3])用于将多个Promise实例包装成一个新的Promise实例
  • 返回的实例就是普通的Promise
  • 接受一个数组作为参数
  • 数组里可以是Promise对象,也可以是别的值,只有Promise会等待状态改变
  • 当所有的Promise都完成,该Promise完成,返回值是全部值的数组
  • 任何一个失败,该Promise失败,返回值是第一个子Promise的结果
Promise.all([1, 2, 3])
    .then( all => {
        console.log('1:', all);
        return Promise.all([ function () {
            console.log('ooxx');
        }, 'xxoo', false]);
    })
    .then( all => {
        console.log('2:', all);
        let p1 = new Promise( resolve => {
            setTimeout(() => {
                resolve('I\'m P1');
            }, 1500);
        });
        let p2 = new Promise( (resolve, reject) => {
            setTimeout(() => {
                resolve('I\'m P2');
            }, 1000);
        });
        let p3 = new Promise( (resolve, reject) => {
            setTimeout(() => {
                resolve('I\'m P3');
            }, 3000);
        });
        return Promise.all([p1, p2, p3]);
    })
    .then( all => {
        console.log('all', all);
    })
    .catch( err => {
        console.log('Catch:', err);
    });

Promise.all() + .map()

const fs = require('fs');
const path = require('path');
const FileSystem = require('./FileSystem');

function findLargest(dir) {
    return FileSystem.readDir(dir, 'utf-8')
        .then( files => {
            return Promise.all( files.map( file => {
                return new Promise (resolve => {
                    fs.stat(path.join(dir, file), (err, stat) => {
                        if (err) throw err;
                        if (stat.isDirectory()) {
                            return resolve({
                                size: 0
                            });
                        }
                        stat.file = file;
                        resolve(stat);
                    });
                });
            }));
        })
        .then( stats => {
            let biggest = stats.reduce( (memo, stat) => {
                if(memo.size < stat.size) {
                    return stat;
                }
                return memo;
            });
            return biggest.file;
        })
}

Promise.resolve()

返回一个fulfilled的Promise实例,或原始的Promise实例

  • 参数为空,返回一个fulfilled的Promise实例
  • 参数是一个普通值,同上,不过fulfilled相应函数会得到这个参数
  • 参数为Promise实例,则返回该实例,不做任何修改
  • 参数为thenable,则立刻执行.then()
Promise.resolve()
    .then( (value) => {
        console.log('Step 1',value);
        return Promise.resolve('Hello');
    })
    .then( value => {
        console.log(value, 'World');
        return Promise.resolve(new Promise( resolve => {
            setTimeout(() => {
                resolve('Good');
            }, 2000);
        }));
    })
    .then( value => {
        console.log(value, ' evening');
        return Promise.resolve({
            then() {
                console.log(', everyone');
            }
        })
    })

输出
Step 1 undefined
Hello World
Good evening
, everyone

Promise.reject()

返回一个reject的Promise实例,或原始的Promise实例

  • Promise.reject()不认thenable
  • 参数为空,返回一个fulfilled的Promise实例
  • 参数是一个普通值,同上,不过fulfilled相应函数会得到这个参数
  • 参数为Promise实例,则返回该实例,不做任何修改
  • 参数为thenable,则立刻执行.then()
let promise = Promise.reject('something wrong');
promise
    .then( () => {
        console.log('it\'s ok');
    })
    .catch( () => {
        console.log('no, it\'s not ok');

        return Promise.reject({
            then() {
                console.log('it will be ok');
            },
            catch() {
                console.log('not yet');
            }
        });
    });

Promise.race()

类似于Promise.all(),区别在于它有任意一个完成就算完成

常见用法

  • 把异步操作和定时器放一起
  • 如果定时器先触发,就认为超时,告知用户

示例

let p1 = new Promise(resolve => {
    // 这是一个长时间的调用
    setTimeout(() => {
        resolve('I\'m P1');
    }, 10000);
});
let p2 = new Promise(resolve => {
    // 这是个稍短的调用
    setTimeout(() => {
        resolve('I\'m P2');
    }, 2000)
});
Promise.race([p1, p2])
    .then(value => {
        console.log(value);
    });

把回调包装成Promise

  • 可读性更好
  • 返回结果可以加入任何Promise队列
const mysql = mysql = require('mysql');

const sql = function(sql, arr) {
    return new Promise(resolve => {
        connection.query(sql, arr, function(err, rows) {
            if (err) {
                throw err;
            }
            resolve(rows);
        })
    })
}


new Promise(resolve => {
        ttt('SELECT * FROM `user` WHERE `username` = ?', req.query.name).then(value => {
            arr.user = value[0];
            resolve(value[0].id)
        })
    })
    test.then(value => {
        return new Promise(resolve => {
            ttt('SELECT * FROM `order` WHERE `userid` = ?', value).then(value => {
                resolve(value[0].id)
            })
        })
    })

把任何异步操作包装成Promise


// 弹出窗体
let confirm = popupManager.confirm('您确定么?');
confirm.promise
    .then(() => {
        // do confirm staff
    })
    .catch(() => {
        // do cancel staff
    });

// 窗体的构造函数
class Confirm {
    constructor() {
        this.promise = new Promise( (resolve, reject) => {
            this.confirmButton.onClick = resolve;
            this.cancelButton.onClick = reject;
        })
    }
}

Fetch API


fetch('some.json')
    .then( response => {
        return response.json();
    })
    .then( json => {
        // do something with the json
    })
    .catch( err => {
        console.log(err);
    });

async/await

  • 赋予javascript以顺序手法编写异步脚本的能力
  • 既保留异步运算符的无阻塞特性,还继续使用同步写法
  • 还能正常使用return/try/catch
  • 基于Promise
function resolveAfter2Seconds(x) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(x);
        }, 2000);
    });
}

async function f1() {
    var x = await resolveAfter2Seconds(10);
    console.log(x); // 10
}
f1();

异步操作

常见异步操作

// 异步操作的常见语法
// https://www.imooc.com/video/16610

// 事件侦听与响应
document.getElementById('start').addEventListener('click', start, false);

function start() {
    // 响应事件,进行相应的操作
}

// jQuery 用 `.on()` 也是事件侦听
$('#start').on('click', start);

### 常见异步操作解决方案
// 回调
// 比较常见的有ajax
$.ajax('http://baidu.com', {
    success: function (res) {
        // 这里就是回调函数了
    }
});

// 或者在页面加载完毕后回调
$(function(){
    // 这里也是回调函数
});

回调地狱

// 回调地狱
// https://www.imooc.com/video/16611

a(function (resultsFromA) {
    b(resultsFromA, function (resultsFromB) {
        c(resultsFromB, function (resultsFromC) {
            d(resultsFromC, function (resultsFromD) {
                e(resultsFromD, function (resultsFromE) {
                    f(resultsFromE, function (resultsFromF) {
                        console.log(resultsFromF);
                    })
                })
            })
        })
    })
});

回调地狱示例

// 遍历目录,找出最大的一个文件
// https://www.imooc.com/video/16611

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

function findLargest(dir, callback) {
    fs.readdir(dir, function (err, files) {
        if (err) return callback(err); // [1]
        let count = files.length; // [2]
        let errored = false;
        let stats = [];
        files.forEach( file => {
            fs.stat(path.join(dir, file), (err, stat) => {
                if (errored) return; // [1]
                if (err) {
                    errored = true;
                    return callback(err);
                }
                stats.push(stat); // [2]

                if (--count === 0) {
                    let largest = stats
                        .filter(function (stat) { return stat.isFile(); })
                        .reduce(function (prev, next) {
                            if (prev.size > next.size) return prev;
                            return next;
                        });
                    callback(null, files[stats.indexOf(largest)]);
                }
            });
        });
    });
}

findLargest('./path/to/dir', function (err, filename) {
    if (err) return console.error(err);
    console.log('largest file was:', filename);
});
// Promise的设计
// https://www.imooc.com/video/16612

new Promise(
    /* 执行器 executor */
    function (resolve, reject) {
        // 一段耗时很长的异步操作

        resolve(); // 数据处理完成

        reject(); // 数据处理出错
    }
)
    .then(function A() {
        // 成功,下一步
    }, function B() {
        // 失败,做相应处理
    });
// 简单的范例-定时执行
// https://www.imooc.com/video/16613

console.log('here we go');
new Promise( resolve => {
    setTimeout( () => {
        resolve('hello');
    }, 2000);
})
    .then( value => {
        console.log( value + ' world');
    });
// 分两次,顺序依次执行
// https://www.imooc.com/video/16614

console.log('here we go');
new Promise( resolve => {
    setTimeout( () => {
        resolve('hello');
    }, 2000);
})
    .then( value => {
        console.log(value);
        return new Promise( resolve => {
            setTimeout( () => {
                resolve('world');
            }, 2000);
        });
    })
    .then( value => {
        console.log( value + ' world');
    });
// 假如一个Promise已经完成了,再.then()会怎样?
// https://www.imooc.com/video/16615

console.log('start');

let promise = new Promise(resolve => {
    setTimeout(() => {
        console.log('the promise fulfilled');
        resolve('hello, world');
    }, 1000);
});

setTimeout(() => {
    promise.then( value => {
        console.log(value);
    });
}, 3000);
// 假如在.then()的函数里面不返回新的Promise,会怎样?
// https://www.imooc.com/video/16616

console.log('here we go');
new Promise(resolve => {
    setTimeout( () => {
        resolve('hello');
    }, 2000);
})
    .then( value => {
        console.log(value);
        console.log('everyone');
        (function () {
            return new Promise(resolve => {
                setTimeout(() => {
                    console.log('Mr.Laurence');
                    resolve('Merry Xmas');
                }, 2000);
            });
        }());
        return false;
    })
    .then( value => {
        console.log(value + ' world');
    });
// 嵌套.then()
// https://www.imooc.com/video/16618

console.log('start');
new Promise( resolve => {
    console.log('Step 1');
    setTimeout(() => {
        resolve(100);
    }, 1000);
})
    .then( value => {
        return new Promise(resolve => {
            console.log('Step 1-1');
            setTimeout(() => {
                resolve(110);
            }, 1000);
        })
            .then( value => {
                console.log('Step 1-2');
                return value;
            })
            .then( value => {
                console.log('Step 1-3');
                return value;
            });
    })
    .then(value => {
        console.log(value);
        console.log('Step 2');
    });
// 随堂小测试
// https://www.imooc.com/video/16619
// 假设doSomething和doSomethingElse返回的都是一个Promise实例
// 原问题地址:http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html
// 译文地址:http://fex.baidu.com/blog/2015/07/we-have-a-problem-with-promises/

// 问题一
doSomething()
    .then(function () {
        return doSomethingElse();
    })
    .then(finalHandler);

// 答案
// doSomething
// |-----------|
//             doSomethingElse(undefined)
//             |------------|
//                          finalHandler(resultOfDoSomethingElse)
//                          |------------|


// 问题二
doSomething()
    .then(function () {
        doSomethingElse();
    })
    .then(finalHandler);

// 答案
// doSomething
// |------------------|
//                    doSomethingElse(undefined)
//                    |------------------|
//                    finalHandler(undefined)
//                    |------------------|


// 问题三
doSomething()
    .then(doSomethingElse())
    .then(finalHandler);

// 答案
// doSomething
// |------------------|
// doSomethingElse(undefined)
// |----------------------------------|
//                    finalHandler(resultOfDoSomething)
//                    |------------------|


// 问题四
doSomething()
    .then(doSomethingElse)
    .then(finalHandler);

// 答案
// doSomething
// |-----------|
//             doSomethingElse(resultOfDoSomething)
//             |------------|
//                         finalHandler(resultOfDoSomethingElse)
//                         |------------------|
// Promise会自动捕获内部异常,并交给rejected响应函数处理-catch捕获
// https://www.imooc.com/video/16620

console.log('here we go');
new Promise( resolve => {
    setTimeout( () => {
        throw new Error('bye');
    }, 2000);
})
    .then( value => {
        console.log( value + ' world');
    })
    .catch( error => {
        console.log( 'Error:', error.message);
    });
// Promise会自动捕获内部异常,并交给rejected响应函数处理-reject响应捕获
// https://www.imooc.com/video/16620

console.log('here we go');
new Promise( (resolve, reject) => {
    setTimeout( () => {
        reject('bye');
    }, 2000);
})
    .then( value => {
        console.log( value + ' world');
    }, value => {
        console.log( 'Error:', value);
    });
// .catch() + .then()
// https://www.imooc.com/video/16621
console.log('here we go');

new Promise(resolve => {
    setTimeout(() => {
        resolve();
    }, 1000);
})
    .then( () => {
        console.log('start');
        throw new Error('test error');
    })
    .catch( err => {
        console.log('I catch:', err);

        // 下面这一行的注释将引发不同的走向
        // throw new Error('another error');
    })
    .then( () => {
        console.log('arrive here');
    })
    .then( () => {
        console.log('... and here');
    })
    .catch( err => {
        console.log('No, I catch:', err);
    });
// 使用`Promise.all()`包装多个Promise实例
// https://www.imooc.com/video/16634

console.log('here we go');
Promise.all([1, 2, 3])
    .then( all => {
        console.log('1:', all);
        return Promise.all([ function () {
            console.log('ooxx');
        }, 'xxoo', false]);
    })
    .then( all => {
        console.log('2:', all);
        let p1 = new Promise( resolve => {
            setTimeout(() => {
                resolve('I\'m P1');
            }, 1500);
        });
        let p2 = new Promise( (resolve, reject) => {
            setTimeout(() => {
                resolve('I\'m P2');
            }, 1000);
        });
        let p3 = new Promise( (resolve, reject) => {
            setTimeout(() => {
                resolve('I\'m P3');
            }, 3000);
        });
        return Promise.all([p1, p2, p3]);
    })
    .then( all => {
        console.log('all', all);
    })
    .catch( err => {
        console.log('Catch:', err);
    });
// 遍历目录,找出最大的一个文件-通过Promise.all()和.map()
// https://www.imooc.com/video/16622

const fs = require('fs');
const path = require('path');
const FileSystem = require('./FileSystem');

function findLargest(dir) {
    return FileSystem.readDir(dir, 'utf-8')
        .then( files => {
            return Promise.all( files.map( file => {
                return new Promise (resolve => {
                    fs.stat(path.join(dir, file), (err, stat) => {
                        if (err) throw err;
                        if (stat.isDirectory()) {
                            return resolve({
                                size: 0
                            });
                        }
                        stat.file = file;
                        resolve(stat);
                    });
                });
            }));
        })
        .then( stats => {
            let biggest = stats.reduce( (memo, stat) => {
                if(memo.size < stat.size) {
                    return stat;
                }
                return memo;
            });
            return biggest.file;
        })
}
// 开发一个爬虫,爬取某网站。(半成品)
// https://www.imooc.com/video/16624

let url = ['http://blog.meathill.com/'];
function fetchAll(urls) {
    return urls.reduce((promise, url) => {
        return promise.then( () => {
            return fetch(url);
        });
    }, Promise.resolve());
}
function fetch(url) {
    return spider.fetch(url)
        .then( content => {
            return saveOrOther(content);
        })
        .then( content => {
            let links = spider.findLinks(content);
            return fetchAll(links);
        });
}
fetchAll(url);
// Promise.resolve()
// https://www.imooc.com/video/16625


console.log('start');

Promise.resolve()
    .then( () => {
        console.log('Step 1');
        return Promise.resolve('Hello');
    })
    .then( value => {
        console.log(value, 'World');
        return Promise.resolve(new Promise( resolve => {
            setTimeout(() => {
                resolve('Good');
            }, 2000);
        }));
    })
    .then( value => {
        console.log(value, ' evening');
        return Promise.resolve({
            then() {
                console.log(', everyone');
            }
        })
    })
// Promise.reject()
// https://www.imooc.com/video/16626


let promise = Promise.reject('something wrong');

promise
    .then( () => {
        console.log('it\'s ok');
    })
    .catch( () => {
        console.log('no, it\'s not ok');

        return Promise.reject({
            then() {
                console.log('it will be ok');
            },
            catch() {
                console.log('not yet');
            }
        });
    });


// Promise.race()
// https://www.imooc.com/video/16627

console.log('start');

let p1 = new Promise(resolve => {
    // 这是一个长时间的调用
    setTimeout(() => {
        resolve('I\'m P1');
    }, 10000);
});
let p2 = new Promise(resolve => {
    // 这是个稍短的调用
    setTimeout(() => {
        resolve('I\'m P2');
    }, 2000)
});
Promise.race([p1, p2])
    .then(value => {
        console.log(value);
    });
// 把回调包装成Promise
// https://www.imooc.com/video/16628



const fs = require('./FileSystem');

fs.readFile('../README.md', 'utf-8')
    .then(content => {
        console.log(content);
    });
// 使用JS包装readFile
// https://www.imooc.com/video/16628



const fs = require('fs');

module.exports = {
    readDir: function (path, options) {
        return new Promise( resolve => {
            fs.readdir(path, options, (err, files) => {
                if (err) {
                    throw err;
                }
                resolve(files);
            });
        });
    },
    readFile: function (path, options) {
        return new Promise( resolve => {
            fs.readFile(path, options, (err, content) => {
                if (err) {
                    throw err;
                }
                resolve(content);
            });
        });
    }
};
// 把任何异步操作包装成Promise
// https://www.imooc.com/video/16629


// 弹出窗体
let confirm = popupManager.confirm('您确定么?');
confirm.promise
    .then(() => {
        // do confirm staff
    })
    .catch(() => {
        // do cancel staff
    });

// 窗体的构造函数
class Confirm {
    constructor() {
        this.promise = new Promise( (resolve, reject) => {
            this.confirmButton.onClick = resolve;
            this.cancelButton.onClick = reject;
        })
    }
}
// Fetch API
// https://www.imooc.com/video/16630


fetch('some.json')
    .then( response => {
        return response.json();
    })
    .then( json => {
        // do something with the json
    })
    .catch( err => {
        console.log(err);
    });
// async/await
// https://www.imooc.com/video/16631


function resolveAfter2Seconds(x) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(x);
        }, 2000);
    });
}

async function f1() {
    var x = await resolveAfter2Seconds(10);
    console.log(x); // 10
}
f1();

标签: promise

添加新评论