Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A practical functional programming library for promises

License

NotificationsYou must be signed in to change notification settings

zhangchiqing/bluebird-promisell

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

71 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A functional programming library for promises.

bluebird-promisell provides a set of composable functions that allows you to write flat async code with promises.

Usage

Write flat async code with "liftp"

Let's say we have the following sync code to get a list of userId.

vargetToken=function(){return'token';};vargetSecret=function(){return'secret';};vargetUserIds=function(token,secret){return[1,2,3];};// Tokenvartoken=getToken();// Secretvarsecret=getSecret();// [UserId]varuserIds=getUserIds(token,secret);console.log(userIds);// [1, 2, 3]

Now, if the sub functionsgetToken,getSecret,getUserIds becomes async (all return Promise),the only change we need to make is "lifting"getUserIds withliftp.

varPromise=require('bluebird');varP=require('bluebird-promisell');vargetToken=function(){returnPromise.resolve('token');};vargetSecret=function(){returnPromise.resolve('secret');};vargetUserIds=function(token,secret){returnPromise.resolve([1,2,3]);};// Promise TokenvartokenP=getToken();// Promise SecretvarsecretP=getSecret();// Promise [UserId]varuserIdsP=P.liftp(getUserIds)(tokenP,secretP);userIdsP.then(console.log);// [1, 2, 3]

Now the code runs async, but it reads like sync code.

Making async calls in parallel with "traversep"

vargetPhotoByUserId=function(userId){if(userId===1){return':)';}elseif(userId===2){return':D';}else{return':-|';}};// Promise TokenvartokenP=getToken();// Promise SecretvarsecretP=getSecret();// Promise [UserId]varuserIdsP=P.liftp(getUserIds)(tokenP,secretP);// Promise [Photo]varphotosP=P.traversep(getPhotoByUserId)(userIdsP);photosP.then(console.log);// [":)", ":D", ":-|"]

Making async calls sequentially with "foldp"

// Promise [UserId]varuserIdsP=P.liftp(getUserIds)(tokenP,secretP);// [Photo] -> Photo -> [Photo]varappendPhotos=function(photos,photo){returnphotos.concat([photo]);};// Promise [Photo]varphotosP=P.foldp(function(photos,userId){// Promise PhotovarphotoP=getPhotoByUserId(userId);returnP.liftp(appendPhotos)(P.purep(photos),photoP);// `P.purep` is equivalent to `Promise.resolve`})([])(userIdsP);photosP.then(console.log);// [":)", ":D", ":-|"]

The above code will fetch photo by userId sequentially. If it fails to fetch the first photo,it will reject the promise without fetching next photo.And it will resolve the promise once all the photos have been fetched.

Wait until the second async call to finish, then return the value of the first async call

Let's say we want to send an email with all the photos, and wait until the email has been sent,then resolve the promise with the photos

Withfirstp, we can wait until the email has been sent, and return the result of photos whichis from the first promise.

varsendEmailWithPhotos=function(photos){returnPromise.resolve('The email has been sent');};// Promise [Photo]varphotosP=P.foldp(function(photos,userId){// Promise PhotovarphotoP=getPhotoByUserId(userId);returnP.liftp(appendPhotos)(P.purep(photos),photoP);// `P.purep` is equivalent to `Promise.resolve`})([])(userIdsP);// Promise StringvarsentP=P.liftp1(sendEmailWithPhotos)(photosP);//          ^^^^^^^^ P.liftp1 is equivalent to P.liftp when there is only one promise to resolve.//                   But P.liftp1 has better performance than P.liftp.P.first(photosP,sentP).then(console.log);// [":)", ":D", ":-|"]

API

Takes any value, returns a resolved Promise with that value

>purep(3).then(console.log)promise3

Transforms a Promise of value a into a Promise of value b

>fmapp(function(a){returna+3;},Promise.resolve(4)).then(console.log)promise7

Takes a Promise, returns a Promise that resolves with undefined when the input promise is resolved,or reject with the same error when the input promise is rejected.

>voidp(purep(12)).then(console.log)promiseundefined

Transforms an array of Promise of value a into a Promise of array of a.

>sequencep([Promise.resolve(3),Promise.resolve(4)]).then(console.log)promise[3,4]

Maps a function that takes a value a and returns a Promise of value b over an array of value a,then usesequencep to transform the array of Promise b into a Promise of array b

>traversep(function(a){returnPromise.resolve(a+3);})([2,3,4])promise[5,6,7]

Performs left-to-right composition of an array of Promise-returning functions.

>pipep([function(a){returnPromise.resolve(a+3);},function(b){returnPromise.resolve(b*10);},])(6);promise90

Takes a function so that this function is able to read input values from resolved Promises,and return a Promise that will resolve with the output value of that function.

>liftp(function(a,b,c){return(a+b)*c;})(Promise.resolve(3),Promise.resolve(4),Promise.resolve(5));promise35

Takes a function and apply this function to the resolved Promise value, and returna Promise that will resolve with the output of that function.

>liftp1(function(user){returnuser.email;})(Promise.resolve({email:'abc@example.com'}));promiseabc@example.com

Takes two Promises and return the first if both of them are resolved

>firstp(Promise.resolve(1),Promise.resolve(2))promise1>firstp(Promise.resolve(1),Promise.reject(newError(3)))promiseError3

Takes two Promises and return the second if both of them are resolved

>secondp(Promise.resolve(1),Promise.resolve(2))promise2>secondp(Promise.resolve(1),Promise.reject(newError(3)))promiseError3

Takes a predicat that returns a Promise and an array of a, returns a Promise of array awhich satisfy the predicate.

>filterp(function(a){returnPromise.resolve(a>3);})([2,3,4])promise[4]

Returns a Promise of value b by iterating over an array of value a, successivelycalling the iterator function and passing it an accumulator value of value b,and the current value from the array, and then waiting until the promise resolved,then passing the result to the next call.

foldp resolves promises sequentially

>foldp(function(b,a){returnPromise.resolve(b+a);})(1)([2,3,4])promise10

Builds a list from a seed value. Accepts an iterator function, which takes the seed and return a Promise.If the Promise resolves to afalse value, it will return the list.If the Promise resolves to a pair, the first item will be appended to the list and the second item will be used as the new seed in the next call to the iterator function.

>unfold(function(a){returna>5 ?Promise.resolve(false) :Promise.resolve([a,a+1]);})(1);promise[1,2,3,4,5]

Transform the rejected Error.

>mapError(function(err){varnewError=newError(err.message);newError.status=400;returnnewError;})(Promise.reject(newError('Not Found')));rejectedpromise

Recover from a rejected Promise

>resolveError(function(err){returnfalse;});

promisefalse

Takes apredict function and atoError function, return a curriedfunction that can take a value and return a Promise.If this value passes the predict, then return a resolved Promise withthat value, otherwise pass the value to thetoError function, andreturn a rejected Promise with the output of thetoError function.

varvalidateGreaterThan0=toPromise(function(a){returna>0;},function(a){returnnewError('value is not greater than 0');});>validateGreaterThan0(10)promise10>validateGreaterThan0(-10)rejectedpromiseError'value is not greater than 0'

Takes two functions and return a function that can take a Promise and return a Promise.If the received Promise is resolved, the first function will be used to map over the resolved value;If the received Promise is rejected, the second function will be used to map over the Error.

Like Promise.prototype.then function, but takes functions first.

varadd1OrReject=bimap(function(n){returnn+1;},function(error){returnnewError('can not add value for '+error.message);});>add1OrReject(P.purep(2))promise3>add1OrReject(Promise.reject(newError('NaN')));promise'can not add value for NaN'

About

A practical functional programming library for promises

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp