使用 Promise

目录

1.Promise是什么. Promise 对象用于表示一个异步操作的最终完成 (或失败), 及其结果值.

首先来听一个故事,有一个名为 createAudioFileAsync() 的函数,如果给出一些配置和两个回调函数,这个函数能异步地生成音频文件。一个回调函数是文件成功创建时的回调,另一个则是出现异常时的回调。

看起来就是这样他就是改了个样子,Promise 是一个被某些函数传出的对象,我们附加回调函数(callback)使用它,而不是将回调函数传入那些函数内部。(这句话很绕口,意思就是写promise底层的是个函数,我们知道promise对象默认是要传进一个function的(

),但是这个function不是传给底层构造他的函数.而是在then()这个触发的时候调用的.总之,我看完后,觉得他真的像Node的事件模块.不过因为同步和异步的差别,他们执行的顺序还是有点差别,但是多次注册,以及多次触发,链式调用.真的写法上又有很大的相似.不过这两个还是不一样的.当然Node事件模块还是可以,调用promise的.这块待之后研究.)

2.约定(你可以先跳过这里,因为你最好在了解他的运行顺序再来看这里,这样你就会明白了)

3.api的讲解

1.链式调用promise.then()的语法

(当 Promise 变成接受状态(fulfilled)时调用的函数。该函数有一个参数,即接受的最终结果(the fulfillment  value)。如果该参数不是函数,则会在内部被替换为 (x) => x,即原样返回 promise 最终结果的函数)这段话真的很书面化,你根本不知道他说的是什么,然后我测试了下这个最终结构就是"foo",同理换成rejected就是错误的原因(UnhandledPromiseRejectionWarning: foo).这两个api后面讲真不行,你先跳过这里,但最好是硬着头皮,怀着疑问,然后在看完rejected和resolve后再来看这里.

到这里,你应该懂了,我前面说的他为什么和event模块这么像.原因在于promise就像注册一样.你一定要用触发函数去触发.then()是,setTimeout也是.所以按照这样分类,可以将promise模块分成两种一种是函数执行触发用的,一种是对promise进行拼接啥的,返回的还是promise,并且还可以和promise自己api函数进行调用.比如all的迭代.

2.Promise.resolve()和 Promise.reject()

1.Promise.resolve(value)

讲人话就是,then(....).resolve这样的写法.

2.Promise.reject(reason);

3. Promise.all(iterable);

4.Promise.race(iterable);

3. 时序

4.嵌套


蓝字是我的重点讲解.但是建议先看完白字.结合https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Using_promises

 

1.Promise是什么. Promise 对象用于表示一个异步操作的最终完成 (或失败), 及其结果值.

首先来听一个故事,有一个名为 createAudioFileAsync() 的函数,如果给出一些配置和两个回调函数,这个函数能异步地生成音频文件。一个回调函数是文件成功创建时的回调,另一个则是出现异常时的回调。

// 成功的回调函数
function successCallback(result) {
  console.log("音频文件创建成功: " + result);
}

// 失败的回调函数
function failureCallback(error) {
  console.log("音频文件创建失败: " + error);
}

createAudioFileAsync(audioSettings, successCallback, failureCallback)

函数 createAudioFileAsync() 被重写为返回 Promise 对象的形式

const promise = createAudioFileAsync(audioSettings);
promise.then(successCallback, failureCallback);


createAudioFileAsync(audioSettings).then(successCallback, failureCallback);

// createAudioFileAsync()  是一个`重写返回Promise对象的形式

看起来就是这样他就是改了个样子,Promise 是一个被某些函数传出的对象,我们附加回调函数(callback)使用它,而不是将回调函数传入那些函数内部。(这句话很绕口,意思就是写promise底层的是个函数,我们知道promise对象默认是要传进一个function的(

new Promise( function(resolve, reject) {...} /* executor */  );

),但是这个function不是传给底层构造他的函数.而是在then()这个触发的时候调用的.总之,我看完后,觉得他真的像Node的事件模块.不过因为同步和异步的差别,他们执行的顺序还是有点差别,但是多次注册,以及多次触发,链式调用.真的写法上又有很大的相似.不过这两个还是不一样的.当然Node事件模块还是可以,调用promise的.这块待之后研究.)

 

2.约定(你可以先跳过这里,因为你最好在了解他的运行顺序再来看这里,这样你就会明白了)

3.api的讲解

p.then(onFulfilled[, onRejected]);

p.then(value => {
  // fulfillment
}, reason => {
  // rejection
});

1.链式调用promise.then()的语法

第一种语法:

Promise.resolve("foo")
// 1. 接收 "foo" 并与 "bar" 拼接,并将其结果做为下一个 resolve 返回。
    .then(function(string) {
        console.log(string)
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
                string += 'bar';
                resolve(string);
            }, 1);
        });
    })
    // 2. 接收 "foobar", 放入一个异步函数中处理该字符串
    // 并将其打印到控制台中, 但是不将处理后的字符串返回到下一个。
    .then(function(string) {
        setTimeout(function() {
            string += 'baz';
            console.log(string);
        }, 1)
        return string;
    })
    // 3. 打印本节中代码将如何运行的帮助消息,
    // 字符串实际上是由上一个回调函数之前的那块异步代码处理的。
    .then(function(string) {
        console.log("Last Then:  oops... didn't bother to instantiate and return " +
            "a promise in the prior then so the sequence may be a bit " +
            "surprising");

        // 注意 `string` 这时不会存在 'baz'。
        // 因为这是发生在我们通过setTimeout模拟的异步函数中。
        console.log(string);
    });

Promise.reject("foo")
// 1. 接收 "foo" 并与 "bar" 拼接,并将其结果做为下一个 resolve 返回。
    .then(function(string) {
        console.log(string)
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
                string += 'bar';
                resolve(string);
            }, 1);
        });

(当 Promise 变成接受状态(fulfilled)时调用的函数。该函数有一个参数,即接受的最终结果(the fulfillment  value)。如果该参数不是函数,则会在内部被替换为 (x) => x,即原样返回 promise 最终结果的函数)这段话真的很书面化,你根本不知道他说的是什么,然后我测试了下这个最终结构就是"foo",同理换成rejected就是错误的原因(UnhandledPromiseRejectionWarning: foo).这两个api后面讲真不行,你先跳过这里,但最好是硬着头皮,怀着疑问,然后在看完rejected和resolve后再来看这里.

这个链式写法,还要根据返回值.

  • 返回了一个值,那么 then 返回的 Promise 将会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值。
  • 没有返回任何值,那么 then 返回的 Promise 将会成为接受状态,并且该接受状态的回调函数的参数值为 undefined
  • 抛出一个错误,那么 then 返回的 Promise 将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值。
  • 返回一个已经是接受状态的 Promise,那么 then 返回的 Promise 也会成为接受状态,并且将那个 Promise 的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值。
  • 返回一个已经是拒绝状态的 Promise,那么 then 返回的 Promise 也会成为拒绝状态,并且将那个 Promise 的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值。
  • 返回一个未定状态(pending)的 Promise,那么 then 返回 Promise 的状态也是未定的,并且它的终态与那个 Promise 的终态相同;同时,它变为终态时调用的回调函数参数与那个 Promise 变为终态时的回调函数的参数是相同的。

测试吧,这个了解下就好了.

可以通过errormessage去获取信息.

Promise.resolve()
  .then(() => {
    // 使 .then() 返回一个 rejected promise
    throw new Error('Oh no!');
  })
  .then(() => {
    console.log('Not called.');
  }, error => {
    console.error('onRejected function called: ' + error.message);
  });

 

箭头函数简写

Promise.reject()
    .then(() => 99, reason => 42) // onRejected returns 42 which is wrapped in a resolving Promise
    .then(solution => console.log('Resolved with ' + solution)); 

了解下执行顺序

如果 onFulfilled 返回了一个 promise,then 的返回值就会被 Promise resolved 或者 rejected。

function resolveLater(resolve, reject) {
    setTimeout(function() {
        resolve(10);
    }, 1000);
}
function rejectLater(resolve, reject) {
    setTimeout(function() {
        reject(new Error('Error'));
    }, 1000);
}

var p1 = Promise.resolve('foo');
var p2 = p1.then(function() {
    return new Promise(resolveLater);
});
var p3 = p1.then(function() {
    return new Promise(rejectLater);
});


p2.then(function(v) {
    console.log('resolved', v);
}, function(e) {
    // not called
    console.error('rejected', e);
});


p3.then(function(v) {
    // not called
    console.log('resolved', v);
}, function(e) {
    console.error('rejected', e);
});

在旧式回调 API 中创建 Promise

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

wait(10000).then(() => saySomething("10 seconds")).catch(failureCallback)

到这里,你应该懂了,我前面说的他为什么和event模块这么像.原因在于promise就像注册一样.你一定要用触发函数去触发.then()是,setTimeout也是.所以按照这样分类,可以将promise模块分成两种一种是函数执行触发用的,一种是对promise进行拼接啥的,返回的还是promise,并且还可以和promise自己api函数进行调用.比如all的迭代.

const promise = doSomething();
doSomething().then(function(result) {
    return doSomethingElse(result);
})
    .then(function(newResult) {
        return doThirdThing(newResult);
    })
    .then(function(finalResult) {
        console.log('Got the final result: ' + finalResult);
    })
    .catch(failureCallback);

dosomething = new Promise((resolve, reject) => {
    console.log('初始化');

    resolve();
})

上面的代码都是不正确的,只是一个逻辑.其中dosomething是需要new promise去构造的.return的都是promise对象.

就是一个链式的写法

catch的后续

new Promise((resolve, reject) => {
    console.log('初始化');

    resolve();
})
    .then(() => {
        throw new Error('有哪里不对了');

        console.log('执行「这个」”');
    })
    .then(
        ()=>{
            console.log("会不会被牵连?")
        }
    ).catch(() => {
        console.log('执行「那个」');
    })
    .then(() => {
        console.log('执行「这个」,无论前面发生了什么');
    });

通常,一遇到异常抛出,Promise 链就会停下来,直接调用链式中的 catch 处理程序来继续当前执行。这看起来和以下的同步代码的执行很相似。"会不会被牵连"就是那样的.

2.Promise.resolve()和 Promise.reject()

 

首先注意几点

1.Promise.resolve(value)

方法返回一个以给定值解析后的Promise 对象。如果该值为promise,返回这个promise;如果这个值是thenable(即带有"then" 方法))这将导致无限递归,因为它试图展平无限嵌套的promise。

讲人话就是,then(....).resolve这样的写法.

Promise.resolve(value);语法

返回一个解析过带着给定值的Promise对象,如果参数是一个Promise对象,则直接返回这个Promise对象。

value(1.将被Promise对象解析的参数。2.一个Promise对象 3.一个thenable。)

 

2.Promise.reject(reason);

reason:表示Promise被拒绝的原因。

返回值;一个给定原因了的被拒绝的 Promise

 

3. Promise.all(iterable);

iterable

一个可迭代对象,如 Array 或 String

Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中  promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。

  • 如果传入的参数是一个空的可迭代对象,则返回一个已完成(already resolved)状态的 Promise
  • 如果传入的参数不包含任何 promise,则返回一个异步完成(asynchronously resolved) Promise。注意:Google Chrome 58 在这种情况下返回一个已完成(already resolved)状态的 Promise
  • 其它情况下返回一个处理中(pending)Promise。这个返回的 promise 之后会在所有的 promise 都完成或有一个 promise 失败时异步地变为完成或失败。 见下方关于“Promise.all 的异步或同步”示例。返回值将会按照参数内的 promise 顺序排列,而不是由调用 promise 的完成顺序决定。
var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'foo');
});

Promise.all([p1, p2, p3])
    .then(([r1, r2, r3]) => {console.log(r1);console.log(r1,r2,r3)});


这样单独传参.


var p1 = Promise.resolve(3);
var p2 = Promise.resolve(312);
var p3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'foo');
});

[p1, p2, p3].reduce((p, f) => p.then(f), Promise.resolve(32)).then(result3 => { console.log(result3);})



const applyAsync = (acc,val) => acc.then(val);
const composeAsync = (...funcs) => x => funcs.reduce(applyAsync, Promise.resolve(x));
const transformData = composeAsync(func1, func2, func3);
const result3 = transformData(data);

砂锅面这两种需要比较下.

4.Promise.race(iterable);

iterable

可迭代对象,类似Array。详见 iterable

 

一个待定的 Promise 只要给定的迭代中的一个promise解决或拒绝,就采用第一个promise的值作为它的值,从而异步地解析或拒绝(一旦堆栈为空)。

race 函数返回一个 Promise,它将与第一个传递的 promise 相同的完成方式被完成。它可以是完成( resolves),也可以是失败(rejects),这要取决于第一个完成的方式是两个中的哪个。

 

3. 时序

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

wait().then(() => console.log(4));
Promise.resolve().then(() => console.log(2)).then(() => console.log(3));
console.log(1); // 1, 2, 3, 4

4.嵌套

doSomethingCritical()
.then(result => doSomethingOptional()
  .then(optionalResult => doSomethingExtraNice(optionalResult))
  .catch(e => {console.log(e.message)})) // 即使有异常也会忽略,继续运行;(最后会输出)
.then(() => moreCriticalStuff())
.catch(e => console.log("Critical failure: " + e.message));// 没有输出

到此为止promise 搞定了.

 

 

再来系统的看下...

 

一个 Promise有以下几种状态:

  • pending: 初始状态,既不是成功,也不是失败状态。
  • fulfilled: 意味着操作成功完成。
  • rejected: 意味着操作失败。

Promise.prototype.constructor

返回被创建的实例函数.  默认为 Promise 函数.创建Promise

const myFirstPromise = new Promise((resolve, reject) => {
  // ?做一些异步操作,最终会调用下面两者之一:
  //
  //   resolve(someValue); // fulfilled
  // ?或
  //   reject("failure reason"); // rejected
});

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值