Promise

Posted 彼得潘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Promise相关的知识,希望对你有一定的参考价值。

promise用来做任务处理,方便串行或并行处理多个任务。在js中Promise对象指的是‘承诺将来会执行’的对象

示例

test函数只关心自身的逻辑,并不关心具体的resolve和reject将如何处理结果。(创建约定)

function test(resolve, reject) 
    let num = Math.random()
    setTimeout(_ => 
           if(num > 0.5) 
               resolve(\'大于0.5\')           
            else 
               reject(\'失败\')           
           
    , 3000)


promise根据状态(约定)来进行下一步任务的执行。

let p = new Promise(test)
p.then(res => 
    console.log(\'成功\' + res)
).catch(err => 
    console.log(\'失败\' + err)
)

一般来说回调嵌套都不会很多,某些情况下,回调嵌套很多时,代码就会非常繁琐,会给编程带来很多麻烦,这种情况称为--回调地狱。
promise是用来解决两个问题的:

  • 回调地狱,代码难以维护,常常第一个函数的输出是第二个函数的输入这种现象
  • promies可以支持多个并发的请求,获取并发请求中的数据

Promis本身只是为了编排任务,优化代码结构,处理多个回调嵌套,解构出回调函数,使得代码易于扩展,维护及易于被理解。

具体使用场景示例

three加载模型函数,是一个异步函数,当加载模型时,加载过程异步执行,并不会阻塞其他函数。如果想在加载的异步函数中添加其他异步执行的请求,或定时器动画,逻辑复杂时会难以扩展。可以使用promise对象来解决,避免产生回调地狱。

未使用promise

loader.load(\'model/Iphone.fbx\', obj => 
  // 回调函数1 --- 加载完成当前模型
  console.log(obj, \'obj\')
  obj.visible = false
  setTimeout(() =>  
    // 回调函数二 --- 定时器 延时添加雾
    // 二层回调嵌套
    scene.fog = new THREE.Fog(0xa0a0a0, 0, 1000);
    // 通过移除以前的模型,延时加载新模型实现转场
    scene.remove(preObj)
    setTimeout(() => 
      // 回调函数三 --- 延时显示新模型,镜头动画拉进至新模型
      // 三层回调嵌套
      obj.visible = true
      let newObjPos = 
        x: obj.position.x,
        y: obj.position.y,
        z: obj.position.z
      
      const tweenB = new TWEEN.Tween(newObjPos).to( x: -20, y: -20, z: -50 , 5000).
      easing(TWEEN.Easing.Quadratic.Out)
      .onUpdate(_ => 
        obj.position.set(newObjPos.x, newObjPos.y, newObjPos.z)
      )
      
      // tween.chain(tweenB)
      tweenB.start() 
      
      
      scene.fog = new THREE.Fog(0xa0a0a0, 600, 1000);
      
    , 500);
    
  , 2000);
  
  
  scene.add(obj)
)

这种情况会有产生3层回调,代码难以扩展。需要使用promise对象处理。

使用promise

定义两个promise,解构出回调函数

function setAction(resolve, reject) 
	setTimeout(() => 
		scene.fog = new THREE.Fog(0xa0a0a0, 0, 1000);
		scene.remove(preObj)
		resolve()
		
	, 2000);

// promise1
let p1 = new Promise(setAction)
// promise2
let p2 = (obj) => 
	
	return new Promise((resolve) => 
		setTimeout(() => 
			obj.visible = true
			let newObjPos = 
				x: obj.position.x,
				y: obj.position.y,
				z: obj.position.z
			
			const tweenB = new TWEEN.Tween(newObjPos).to( x: -20, y: -20, z: -50 , 5000).
			easing(TWEEN.Easing.Quadratic.Out)
			.onUpdate(_ => 
				obj.position.set(newObjPos.x, newObjPos.y, newObjPos.z)
			)
			
			// tween.chain(tweenB)
			tweenB.start() // Start the tween immediately.
			
			
			scene.fog = new THREE.Fog(0xa0a0a0, 600, 1000);
			resolve()
			
		, 500);
	)

使用promise解构后的函数如下,解构后单个函数逻辑被拆分,降低了复杂度。

loader.load(\'model/Iphone.fbx\', obj => 
    console.log(obj, \'obj\')
    obj.visible = false
    p1.then(_ => 
        console.log(\'执行p1\')
        p2(obj).then(_ => 
            console.log(\'执行p2\');
        )
    )
    
    scene.add(obj)
)

以上是关于Promise的主要内容,如果未能解决你的问题,请参考以下文章

promise.all 怎么用

手写promise啥水平

实现promise.all方法

promise知识盲区整理

Promise 用法

Promise