promise

作者: 郑馋师 | 来源:发表于2019-12-13 23:23 被阅读0次

一般回调

  1. 一般回调会得到两个结果,成功或者失败
  2. 此时回调需要接受这两个参数,所以要搞两个回调来接受

对象中两个回调缩写的方法

缩写

这个方法的不足

  1. 名称不规范,可能是success可能是done

  2. 容易出现回调地狱,也就是会使得代码变得更加难以理解、追踪、调试和维护

    回调地狱
  3. 难以进行错误处理

promise

可以实现关注点分离

let evt=a()
b(evt)
c(evt)

(1)b,c不需要牵扯到a的调用细节。
(2)a不需要知道或关注b,c是否存在。

回调则相反:

function a(b,c){
// do something
if(evt?) b(evt);
else c(evt)
}

(1)b,c需要牵扯到a的调用细节。
(2)a需要知道或关注b,c是否存在。

promise信任问题

promise调用then时,提供给then的回调只会被异步调用,(不同于回调,可能被同步也可能被异步调用),这些被调度的回调会在下一个异步时间点上依次被立即调用(插在异步队列的最前面)。

并且,这些then异步调用的任务队列会插在当前事件循环tick之后,而不是添加到事件循环队列的末尾(插在当前事件的末尾,下一个事件之前)。

promise会自动防止Zalgo的出现,因为只能被异步调用,不同于回调可能被同步也可能被异步调用,因此不用担心竞态条件。

(既可能在现在(同步)也可能在将来(异步)调用回调,由这种同步或异步行为引起的不确定性,被称为Zalgo)

promise用法

创建新的promise

一定要记住,使用return new Promise((resolve, reject)=> {}) 就可以构造一个 Promise 对象
下面是完整的eg

ajax=(method,url,option)=>{
    return new Promise((resolve,reject)=>{
        const {success,fail}=options
        //析构语法
        //相当于options.success=success
        //options.fail=fail的缩写

        //下面是AJAX的四步构成
        const request=new XMLHttpRequest()
        request.open(method,url)
        request.onreadystatechange=()=>{
            if (request.readyState===4){
                if(request.status<400){
                    resolve.call(undefined,request.response)
                }
                else  if(request.status>=400){
                    reject.call(undefined,request)
                }
            }
        }
        request.send()
    })
}

eg里面比较吊的语法解析
构析语法

const {success,fail}=options
        //相当于options.success=success
        //options.fail=fail两句的缩写

调用的时候

//普通回调
aiax(`get`,`/xxx`,{
    success(response){},fail:(request,status)=>{}
})
//有两个回调,还是用了success和fail

//promise写法
aiax(`get`,`/xxx`.then((response)=>{},(request)=>{}))
//虽然也是回调,但不需要记住success和fail,then的第一个参数就一定是success
//第二个一定是fail
//这时候ajax返回了一个含有.then()方法的对象

总结

第一步

  • 是使用return new Promise((resolve, reject)=> {}) 构造一个 Promise 对象
  • 任务成功的时候调用resolve(result),失败则是reject(error)
  • resolve和reject会自己再去调用成功和失败的函数
    第二步
  • 使用.then(success,fail)传入成功和失败的函数

缺点

  1. 无法使用请求头
  2. POST无法上传数据
    这些都可以通过axios解决

比较高级的用法

  1. json可以自动响应,发现其content-type是json会自动调用JSON.parse
  2. 请求拦截器,这是加在请求里面的东西
  3. 响应拦截器,加在响应里面的东西
  4. 生成不同实例和对象,仅仅用于复杂场景
    Tips:
  5. Promise 不是前端发明的
  6. Promise 是目前前端解决异步问题的统一方案
  7. window.Promise 是一个全局函数,可以用来构造 Promise 对象
  8. 构造出来的 Promise 对象含有一个 .then() 函数属性

创建新的promise

resolve 和 reject 可以改成任何其他名字,不影响使用,但一般就叫这两个名字
任务成功的时候调用 resolve,失败的时候调用 reject
resolve 和 reject 都只接受一个参数
resolve 和 reject 并不是 .then(succes, fail) 里面的 success 和 fail,resolve 会去调用 success,reject 会去调用 fail

几个重要的api

Promise.prototype.then()

then() 方法返回一个 Promise。它最多需要有两个参数:Promise 的成功和失败情况的回调函数。

let promise1 = new Promise(function(resolve, reject) {
  resolve('Success!');
});

promise1.then(function(value) {
  console.log(value);
  // expected output: "Success!"
});

Promise.all()

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

var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
});
// expected output: Array [3, 42, "foo"]

Promise.race

Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。

var promise1 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 500, 'one');
});

var promise2 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 100, 'two');
});

Promise.race([promise1, promise2]).then(function(value) {
  console.log(value);
  // Both resolve, but promise2 is faster
});
// expected output: "two"

相关文章

网友评论

      本文标题:promise

      本文链接:https://www.haomeiwen.com/subject/rwlfnctx.html