普通异步函数如何与Promise配合使用?
发布于 8 年前 作者 MysteryCoke 3200 次浏览 来自 问答

学了一天的Promise,还是不太理解Promise。 然后凭着自己的理解写下如下对比的代码,希望有人能帮我理解Promise.

假设在express里,我希望先检查请求目录的正确性(这步不是异步的),再检查文件权限,最后发送文件,并检查结果,我普通的写法如下。

server.get('/file',(req,res)=>{
    let filepath=pathcheck(req.query.path,req.query.filename);
    if(!filepath) res.json({message: 'invalid path'});    
    else fs.access(filepath,fs.R_OK,(err)=>{
	if(err) res.json(err);
	else res.sendFile(filepath,{},(err)=>{
	    if(err) res.json(err);
	    else console.log('success');
	});
    });
});

这是Promise的。

server.get('/file',(req,res)=>{
    let invalidcheck=new Promise((resolve,reject)=>{
	let filepath=pathcheck(req.query.path,req.query.filename);
	if(!filepath) reject({message: 'invalid path'});
	else resolve(filepath,fs.R_OK);
    });
    
    let accesscheck=invalidcheck.then((path,mode)=>{
	return new Promise((resolve,reject)=>{
	    fs.access(path,mode,(err)=>{
		if(err) reject(err);
		else resolve(path);
	    });
	});
    });

    let sendcheck=accesscheck.then((path)=>{
	return new Promise((resolve,reject)=>{
	    res.sendFile(path,{},(err)=>{
		if(err) reject(err);
		else resolve('success');
	    });
	});
    });

    let resultcheck=sendcheck.then(console.log).catch(res.json);
});

代码不一定正确,但这写法和大家普遍的写法一样吗?

7 回复

楼主可以试试我做的异步处理插件,简单入门 https://github.com/1340641314/fors

@1340641314 不好意思,没有认真看你的插件,但是这插件和async.waterfall感觉有点像啊(再一次,我没有认真看,如果有本质上的巨大差异,劳烦讲解)。 再者,我还是初学者,还是希望学习语言自带的方法,还不准备使用框架,所以我现在希望学习Promise的写法,能给我讲解下吗?

可以把先每部分的异步(甚至同步)函数单独封装成Promise. 比如你的accesscheck,sendcheck实际上和invalidcheck无关的. 不需要写在invalidcheck.then后面.

然后可以在实际业务需求中 按需链型调用 上一个then return 下一个promise 然后继续then

手机编辑… 上电脑再帮你改下代码

来自酷炫的 CNodeMD

@Kaijun 我不太明白你的意思,invalidcheck需要在acesscheck之前判断,尽管invalidcheck并没有异步操作,但我希望整个过程有一个同一的出错出口,就是最后那里的catch:

let resultcheck=sendcheck.then(console.log).catch(res.json);

这样我就不用多写一句res.json(err),也不用直接return或把剩余部分括起来。 不写在Promise里面,有什么更好的方法吗?

server.get('/file',(req,res)=>{
    let invalidcheck=(path) => new Promise((resolve,reject)=>{
	  ...
    });
    
    let accesscheck=(path,mode) => new Promise((resolve,reject)=>{
	    ...
	});

    let sendcheck=(path) => new Promise((resolve,reject)=>{
	    ...
	});

    let resultcheck=invalidcheck.then((path)=> {
		return accesscheck(path, mode)
	}).then((path)=>{
		return sendcheck(path)
	}).then((message)=>{
		console.log(message)
	})
});

大概是这样 promise then中return另一个promise的话 这个promise resolve的data 会传到下个then中

自己感受下~

@Kaijun 好的,谢谢

回到顶部