Promise入门_2

3. Promise 的几个关键问题

1. 如何改变 promise 的状态?

(1)resolve(value):如果当前是 pending 就会变为 resolved

(2)reject(reason):如果当前是 pending 就会变为 rejected

(3)抛出异常:如果当前是 pending 就会变为 rejected

const p = new Promise((resolve, reject) => {
  //resolve(1) // promise变为resolved成功状态
  //reject(2) // promise变为rejected失败状态
  throw new Error('出错了') // 抛出异常,promise变为rejected失败状态,reason为抛出的error
})
p.then(
  value => {},
  reason => {console.log('reason',reason)}
)
// reason Error:出错了

2. 一个 promise 指定多个成功/失败回调函数(调用多次then方法),都会调用吗?

如果promise里面用reject函数改变了promise实例的状态,那就要在外面的then函数里给它绑定一个失败的回调函数,不然会报错。
promise 改变为对应状态时都会调用。

const p = new Promise((resolve, reject) => {
  //resolve(1)
  reject(2)
})
p.then(
  value => {},
  reason => {console.log('reason',reason)}
)
p.then(
  value => {},
  reason => {console.log('reason2',reason)}
)
// reason 2
// reason2 2

3. 改变 promise 状态和指定回调函数谁先谁后?(意思是promise的代码在运行时,resolve改变状态(调用)的代码先执行还是then方法绑定回调函数先执行)

如:
image

都有可能,常规是先绑定回调再改变状态,但也可以先改状态再绑定回调。这涉及到事件轮询。

指定回调和调用回调是两个概念,指定回调并没有调用,指定回调也属于初始化代码。调用回调是属于回调代码。绑定回调代码不等于执行回调。

执行器函数是同步执行的,一般来说会先改变状态。如果resolve调用写在定时器里,则then先执行绑定函数,因为这时候里面的resolve调用会变成异步操作了,有事件轮询里的事件模块调用。

promise是微任务先执行,setTimeou里面是回调函数,js走到这里会将其给到定时器管理模块,触发后放入宏任务轮询,这个时候主线程不会等resolve,会执行初始化代码then方法,但是处理结果的回调(then方法里面的匿名函数)会等状态改变后才被调用。

then是异步微任务,所以then方法里面的参数也(两个匿名函数)属于回调代码,会等初始化代码执行完毕后等它们的Promise实例的状态改变时才会被调用。注意:new Promise里面的回调函数是初始化代码,但是如果里面套定时器,那么定时器里的回调函数就是回调代码,尽管在定时器的回调里调用改变promise状态的方法也是一样,这时候主线程不会等。如:
image

1,
image

2
image

  • 如何先改状态再指定回调?
    (1)在执行器中直接调用 resolve()/reject()
    (2)延迟更长时间才调用 then()
let p = new Promise((resolve, reject) => {
  // setTimeout(() => {
      resolve('OK');
  // }, 1000); // 有异步就先指定回调,否则先改变状态
});

p.then(value => {
  console.log(value);
},reason=>{
  
})
  • 什么时候才能得到数据?(意思是回调函数什么时候执行)
    (1)如果先指定的回调,那当状态发生改变时,回调函数就会调用得到数据
    (2)如果先改变的状态,那当指定回调时,回调函数就会调用得到数据
new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1) // 改变状态
  }, 1000)
}).then( // 指定回调函数 (先指定)
  value => {},
  reason =>{}
)

此时,先指定回调函数,保存当前指定的回调函数;后改变状态(同时指定数据),然后异步执行之前保存的回调函数。

new Promise((resolve, reject) => {
  resolve(1) // 改变状态
}).then( // 指定回调函数
  value => {},
  reason =>{}
)

这种写法,先改变的状态(同时指定数据),后指定回调函数(不需要再保存),直接异步执行回调函数。


4. promise.then() 返回的新 promise 的结果状态由什么决定?

then方法总会返回一个新的Promise的实例:
(1)简单表达:由 then() 指定的回调函数执行的结果决定

let p = new Promise((resolve, reject) => {
  resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
  console.log(value);
}, reason => {
  console.warn(reason);
});

console.log(result);

image


(2)详细表达:
① 如果抛出异常,新 promise 变为 rejectedreason 为抛出的异常

let p = new Promise((resolve, reject) => {
  resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
  //1. 抛出错误
  throw '出了问题';
}, reason => {
  console.warn(reason);
});

console.log(result);

image

② 如果返回的是非 promise 的任意值,新 promise 变为 resolved,value 为返回的值

let p = new Promise((resolve, reject) => {
  resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
	//2. 返回结果是非 Promise 类型的对象
	return 521;
}, reason => {
  console.warn(reason);
});

console.log(result);

image

③ 如果返回的是另一个新 promise,此 promise 的结果就会成为新 promise 的结果

let p = new Promise((resolve, reject) => {
  resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
	//3. 返回结果是 Promise 对象
	return new Promise((resolve, reject) => {
		// resolve('success');
		reject('error');
	});
}, reason => {
  console.warn(reason);
});

console.log(result);

image

new Promise((resolve, reject) => {
  resolve(1)
}).then(
  value => {
    console.log('onResolved1()', value)
  },
  reason => {
    console.log('onRejected1()', reason)
  }
).then(
  value => {
    console.log('onResolved2()', value)
  },
  reason => {
    console.log('onRejected2()', reason)
  }
)
//结果:
// onResolved1() 1
// onResolved2() undefined

5.promise 如何串联多个操作任务?

(1)promise 的 then() 返回一个新的 promise,可以并成 then() 的链式调用
(2)通过 then 的链式调用串联多个同步/异步任务

let p = new Promise((resolve, reject) => {
  setTimeout(() => {
      resolve('OK');
  }, 1000);
});

p.then(value => {
  return new Promise((resolve, reject) => {
      resolve("success");
  });
}).then(value => {
  console.log(value); // success
}).then(value => {
  console.log(value); // undefined
})

image

        let p=new Promise((resolve,reject)=>{
            setTimeout(() => {
                resolve("success");
            }, 2000);
        });

        let rp=p.then(value=>{
            console.log(value);//结果:success   
            //.then的确返回promise对象,但这个对象的值由回调返回的值决定,
            //这里没有声明返回值,所以返回undefined,
            //那么下一个then获取到的值就是undefined。      
        },reason=>{
            console.log(reason);
        });     

        let rp2=rp.then(value=>{
            console.log("成功1");
            console.log(value);//结果:undefind   
        },reason=>{
            console.log("失败1");
        });

        let rp3=rp2.then(value=>{
            console.log("成功2");
            console.log(value);//结果:undefind  
        },reason=>{
            console.log("失败2");
        });

image


6.Promise 异常穿透(传透)?

(1)当使用 promise 的 then 链式调用时,可以在最后指定失败的回调
(2)前面任何操作出了异常,都会传到最后失败的回调中处理

new Promise((resolve, reject) => {
   //resolve(1)
   reject(1)
}).then(
  value => {
    console.log('onResolved1()', value)
    return 2
  }
).then(
  value => {
    console.log('onResolved2()', value)
    return 3
  }
).then(
  value => {
    console.log('onResolved3()', value)
  }
).catch(
  reason => {
    console.log('onRejected1()', reason)
  }
)
// onRejected1() 1

相当于这种写法:多写了很多reason => {throw reason}

new Promise((resolve, reject) => {
   //resolve(1)
   reject(1)
}).then(
  value => {
    console.log('onResolved1()', value)
    return 2
  },
  reason => {throw reason} // 抛出失败的结果reason
).then(
  value => {
    console.log('onResolved2()', value)
    return 3
  },
  reason => {throw reason} // 抛出失败的结果reason
).then(
  value => {
    console.log('onResolved3()', value)
  },
  reason => {throw reason} // 抛出失败的结果reason
).catch(
  reason => {
    console.log('onRejected1()', reason)
  }
)
// onRejected1() 1

所以失败的结果是一层一层处理下来的,最后传递到 catch 中。

或者,将 reason => {throw reason} 替换为 reason => Promise.reject(reason) 也是一样的。


7.中断 promise 链

当使用 promise then 链式调用时,在中间中断,不再调用后面的回调函数

办法:在回调函数中返回一个 pending 状态的 promise 对象

new Promise((resolve, reject) => {
   //resolve(1)
   reject(1)
}).then(
  value => {
    console.log('onResolved1()', value)
    return 2
  }
).then(
  value => {
    console.log('onResolved2()', value)
    return 3
  }
).then(
  value => {
    console.log('onResolved3()', value)
  }
).catch(
  reason => {
    console.log('onRejected1()', reason)
  }
).then(
  value => {
    console.log('onResolved4()', value)
  },
  reason => {
    console.log('onRejected2()', reason)
  }
)
// onRejected1() 1
// onResolved4() undefined

为了在 catch 中就中断执行,可以这样写:

new Promise((resolve, reject) => {
   //resolve(1)
   reject(1)
}).then(
  value => {
    console.log('onResolved1()', value)
    return 2
  }
).then(
  value => {
    console.log('onResolved2()', value)
    return 3
  }
).then(
  value => {
    console.log('onResolved3()', value)
  }
).catch(
  reason => {
    console.log('onRejected1()', reason)
    return new Promise(() => {}) // 返回一个pending的promise
  }
).then(
  value => {
    console.log('onResolved4()', value)
  },
  reason => {
    console.log('onRejected2()', reason)
  }
)
// onRejected1() 1

catch 中返回一个新的 promise,且这个 promise 没有结果。

由于,返回的新的 promise 结果决定了后面 then 中的结果,所以后面的 then 中也没有结果。

这就实现了中断 promise链的效果。

posted @   青仙  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示