Skip to content

Instantly share code, notes, and snippets.

@RammusXu
Created April 29, 2016 07:48
Show Gist options
  • Save RammusXu/69e8c2471b1cda4bb0cacbca823da3ef to your computer and use it in GitHub Desktop.
Save RammusXu/69e8c2471b1cda4bb0cacbca823da3ef to your computer and use it in GitHub Desktop.
how to refactor it ?
var request = [
profileUtil.createUser('[email protected]', 'qwer1234', 'test', 'Company'),
profileUtil.createUser('[email protected]', 'qwer1234', 'test2', 'Company'),
];
request[0].then(function(value) {
return request[1];
})
.then(function(value) {
return request[2];
})
.then(function (value) {
done();
})
.catch(function(reason) {
console.log(reason);
// (reason.errmsg).should.include('duplica2te');
done();
});
@RammusXu
Copy link
Author

RammusXu commented Apr 29, 2016

createUser

// Initialize
var async = require('async'),
    mongoose = require("mongoose");

// Test module
var Profile = require('./schema/profile.js');
var CompanyProfile = require('./schema/profile.js').CompanyProfile;
var TalentProfile = require('./schema/profile.js').TalentProfile;

// pinglib
var pinglib = require('pinglib');
var User = pinglib.User;

var main = {};

main.createUser = function(email, pwd, username, type) {
    return new Promise(function(resolve, reject) {
        console.log("name", username);
        var newProfile;
        if (type === 'Company') {
            newProfile = new CompanyProfile();
            newProfile.username = username;

        } else if (type === 'Talent') {
            newProfile = new TalentProfile();
            newProfile.username = username;

        } else {
            reject("Can't recognize type = " + type);
        }

        var newUser = new User();
        newUser.system_parameters = 1;
        newUser.email = email;
        newUser.pwd = pwd;
        newUser.custom = { _profile: newProfile._id };

        newProfile.save()
            .then(function(doc) {
                console.log("newProfile save", username);
                return newUser.save();
            })
            .then(function(doc) {
                console.log("resolve User", username);
                return resolve(doc);
            })
            .catch(function(reason) {
                console.log("reject ", username);
                Profile.findByIdAndRemove(newProfile)
                    .then(function(doc) {
                        console.log("rollback Profile", username);
                        return reject(reason);
                    });
            });



    });
};

module.exports = main;

unit test

var requests = [
            profileUtil.createUser('[email protected]', 'qwer1234', 'test', 'Company'),
            profileUtil.createUser('[email protected]', 'qwer1234', 'test2', 'Company'),
        ];

        requests[0].then(function(value) {
                console.log("r0", value);
                return requests[1];
            })
            .then(function(value) {
                console.log("r1", value);
                done();
            })
            .catch(function(reason) {
                console.log("reject requests");
                done();
            });

console log

name test
name test2
newProfile save test
newProfile save test2
resolve User test
r0 { menu_crud: [],
  _id: 57231f3e0acd2dfc3ae61372,
  email: '[email protected]',
  pwd: 'qwer1234',
  custom: { _profile: 57231f3e0acd2dfc3ae61371 },
  __v: 0 }
reject  test2
rollback Profile test2
reject requests
name test
name test2
newProfile save test2
newProfile save test
resolve User test2
reject  test
rollback Profile test
reject

@sdf611097
Copy link

sdf611097 commented Apr 29, 2016

when promise executing, i == request.length, so it will not work as expected
just let i is a copy(as a arg in a function), so that it will works

function ok(msg){
    return new Promise(function(resolve, reject){
        setTimeout(function(){
            console.log(msg);
            resolve(msg);
        },1000);
    });
}

function fail(msg){
    return new Promise(function(resolve, reject){
        setTimeout(function() {
            console.log(msg);
            reject(new Error('err'));
        },1000);
    });
}

function done(){
    console.log('done');
}    

var request = [ok('1'), ok('2'), fail('123'), ok('3')];

var promise = Promise.resolve('start');

for(var i=0; i<request.length; i++) {
    function exec(i){
        promise = promise.then(function(value){
            console.log('value', value);
            return request[i];
        });
    }
    exec(i);
}
//all resolved
promise.then(function  (value) {
    console.log('value', value);
    done();
})
.catch(function(error) {
    console.log('err', error);
    // (error.errmsg).should.include('duplica2te');
    done();
});

@RammusXu
Copy link
Author

這樣還是會執行

log

in 1
in 2
in 3
value start
1
2
123
3
value 1
value 2
function ok(msg){
    return new Promise(function(resolve, reject){
        console.log("in", msg);
        setTimeout(function(){
            console.log(msg);
            resolve(msg);
        },1000);
    });
}

function fail(msg){
    return new Promise(function(resolve, reject){
        setTimeout(function() {
            console.log(msg);
            reject(new Error('err'));
        },1000);
    });
}

function done(){
    console.log('done');
}    

var request = [ok('1'), ok('2'), fail('123'), ok('3')];

var promise = Promise.resolve('start');

for(var i=0; i<request.length; i++) {
    function exec(i){
        promise = promise.then(function(value){
            console.log('value', value);
            return request[i];
        });
    }
    exec(i);
}
//all resolved
// promise.then(function  (value) {
//     console.log('value', value);
//     done();
// })
// .catch(function(error) {
//     console.log('err', error);
//     // (error.errmsg).should.include('duplica2te');
//     done();
// });

@sdf611097
Copy link

其實他已經是對的了,只是他在request宣告時就開始執行了

ok('1') 這時候就已經執行了

所以這case可以改成下面這樣,就能一個接著一個做

function job(code){
    return new Promise(function(resolve, reject){
        setTimeout(function(){
            console.log(code);
            if(code >=0){
                resolve(code);
            }else{
                reject(code);
            }
        },1000);
    });
}

function done(){
    console.log('done');
}

var request = [1, 2, -1, 3];

var promise = Promise.resolve('start');

for(var i=0; i<request.length; i++) {
    function exec(i) {
        promise = promise.then(function(value){
            console.log('value', value, i);

            return job(i);
        });
    }
    exec(i);
}
//all resolved
promise.then(function  (value) {
    console.log('value', value);
    done();
})
.catch(function(error) {
    console.log('err', error);
    // (error.errmsg).should.include('duplica2te');
    done();
});

@sdf611097
Copy link

或是把job包成function 需要的時候再執行()

function ok(msg){
    return function(){
        return new Promise(function(resolve, reject){
            setTimeout(function(){
                console.log(msg);
                resolve(msg);
            },1000);
        });
    }
}

function fail(msg){
    return function(){
        return new Promise(function(resolve, reject){
            setTimeout(function() {
                console.log(msg);
                reject(new Error('err'));
            },1000);
        });
    }
}

function done(){
    console.log('done');
}    

var jobs = [ok('1'), ok('2'), fail('123'), ok('3')];

var promise = Promise.resolve('start');

for(var i=0; i<jobs.length; i++) {
    function exec(i) {
        promise = promise.then(function(value){
            console.log('value', value, i);
            //start exec here
            return jobs[i]();
        });
    }
    exec(i);
}
//all resolved
promise.then(function  (value) {
    console.log('value', value);
    done();
})
.catch(function(error) {
    console.log('err', error);
    // (error.errmsg).should.include('duplica2te');
    done();
});

@sdf611097
Copy link

By the way,

如果for loop那邊用的i是用let宣告的(不是var),應該就不會有這問題了

node要用es6語法的話,開頭加'use strict'
就可以用const, let宣告,可以避免很多var常見的陷阱(hoisting)

另外也支援這樣的匿名function

//1 原本宣告方法
let f1 = function(arg1,arg2) {
    return arg1+arg2;
}
//2 單行,不用return跟分號
let f2 = (arg1, arg2)=> arg1+arg2

//3 多行,要自己加return
let f3 = (arg1, arg2)=> {
    return arg1+arg2;
}

/* 
其他還有一些list的operation
像是filter, map
 */
let arr = [1,2,3];
//[2,4,6]
console.log(arr.map(value=>value*2));
//[2,3]
console.log(arr.filter(value=>value>=2));
//[1,2,3]
console.log(arr);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment