2016-09-08 3 views
1

私はいくつかの数値を保存する約束事を作成し、約束事を得て(coライブラリを使って)結果を出力します。しかし、私が理解していないことは、出力を印刷するときに同じレコードを10回印刷することです。ここでmongooseとes6が期待どおりに動作しないと約束します

はコードです:

/tmp/test$ node m 
{"__v":0,"num":9,"_id":"57d1931037a370055f51977c"} 
{"__v":0,"num":9,"_id":"57d1931037a370055f51977c"} 
{"__v":0,"num":9,"_id":"57d1931037a370055f51977c"} 
{"__v":0,"num":9,"_id":"57d1931037a370055f51977c"} 
{"__v":0,"num":9,"_id":"57d1931037a370055f51977c"} 
{"__v":0,"num":9,"_id":"57d1931037a370055f51977c"} 
{"__v":0,"num":9,"_id":"57d1931037a370055f51977c"} 
{"__v":0,"num":9,"_id":"57d1931037a370055f51977c"} 
{"__v":0,"num":9,"_id":"57d1931037a370055f51977c"} 
{"__v":0,"num":9,"_id":"57d1931037a370055f51977c"} 

注私は約束の内部で変数xを宣言した場合、その後、私は(期待どおりの結果を得るために、異なる例えば10:ここで

'use strict' 
const Promise = require('bluebird'); 
const co = require('co'); 
const _ = require('lodash'); 
const mongoose = require('mongoose'); 

// plug in the bluebird promise library for mongoose 
mongoose.Promise = Promise; 

mongoose.connect('mongodb://localhost:27017/nodejs_testing'); 

const numSchema = new mongoose.Schema({ 
    num: { type: Number, required: true } 
}); 
const Num = mongoose.model('Num', numSchema); 

let promises = []; 
let x; 

// create an array of promises to save some numbers 
for (let i = 0; i < 10; ++i) { 
    let p = new Promise((resolve,reject) => { 
    x = Num(); 
    x.num = i; 
    x.save((err) => { 
     if (err) { 
     reject(err); 
     } else { 
     resolve(x); 
     } 
    }); 
    }); 
    promises.push(p); 
}; 

// yield all the promises, then print out the results 
co(function *() { 
    let res = yield Promise.all(promises); 
    _.each(res, item => { 
    console.log(JSON.stringify(item)); 
    }); 
    mongoose.disconnect(); 
}); 

が出力されます出力内の数字)。言い換えれば、私がこの変更を行うと(下記参照)、それは期待どおりに動作します:

let p = new Promise((resolve,reject) => { 
    let x = Num(); // <--- declare x inside the promise 
    . 
    . 
    }); 

私の質問は、このように動作しますか?私が正確に同じタイプのテストではなくmongodb/mongooseを使用して繰り返し、いくつかの数字を印刷するだけであれば、Promise外でxが宣言されていても期待どおりに動作することに注意してください。以下のサンプルコード:

'use strict' 
const Promise = require('bluebird'); 
const co = require('co'); 
const _ = require('lodash'); 

class Number { 
    constructor(num) { 
    this.num = num; 
    } 
}; 

let x; 
let promises = []; 

for (let i = 0; i < 10; ++i) { 
    let p = new Promise((resolve,reject) => { 
    setTimeout(() => { 
     x = new Number(i); 
     resolve(x); 
    }, 300); 
    }); 
    promises.push(p); 
}; 

co(function *() { 
    let res = yield Promise.all(promises); 
    _.each(res, item => { 
    console.log(JSON.stringify(item)); 
    }); 
}); 

出力:

/tmp/test$ node t 
{"num":0} 
{"num":1} 
{"num":2} 
{"num":3} 
{"num":4} 
{"num":5} 
{"num":6} 
{"num":7} 
{"num":8} 
{"num":9} 

答えて

2

差が対非マングースをマングースされていません。あなたのコードはさまざまなことをしています。 xは、コードは非常にすべての反復は、変数を再利用し、であることをループの外で宣言され

let p = new Promise((resolve,reject) => { 
    x = Num();    // *** A 
    x.num = i; 
    x.save((err) => { 
    if (err) { 
     reject(err); 
    } else { 
     resolve(x);   // *** B 
    } 
    }); 
}); 

...:あなたの最初の例で

、あなたは(***コメントを参照してください)持っています。

上記のAとBの文は、互いにという非同期でという文が出現することに注意してください。 Bが発生するまでには、すべての反復が既に行われていますA; Bの最後のの値がxに割り当てられているため、解決するために使用されているため、すべて同じ値で解決されます。あなたの第二の例と比較すると

let p = new Promise((resolve,reject) => { 
    setTimeout(() => { 
    x = new Number(i);  // *** A 
    resolve(x);   // *** B 
    }, 300); 
}); 

2が今お互いに同期起こっていることに注意してください。 Bは、解像度を変更するたびに現在の値であるxを使用します。

これは、この2つの動作の違いの理由です。内

基本的に、xは、それが使われているところにたくさんの近くに宣言する必要があり、約束のinitコールバック:

//let x;       // *** Not here 

// create an array of promises to save some numbers 
for (let i = 0; i < 10; ++i) { 
    let p = new Promise((resolve,reject) => { 
    let x = Num();    // *** Here 
    x.num = i; 
    x.save((err) => { 
     if (err) { 
     reject(err); 
     } else { 
     resolve(x); 
     } 
    }); 
    }); 
} 

ルールを覚えておいてくださいです:常にあなたができる最も狭いスコープで宣言します。

+1

をはい、私は約束内部でx変数を宣言するために優れていた知っていたし、そうすることが、問題を解決することしかし、私はなぜ私が自分の行動を得ているのか理解したかっただけです。とにかく、素晴らしい説明、ありがとう! – dcp

2

これは、xがforループのスコープ外にあるためです。 forループを実行すると、他の変数xのインスタンスを変更するのではなく、元の値xの値を再割り当てします。何が起こっていることは、最終的な値xが上のかかることである他の値はモンゴに保存されていると、あなたがしたい場合はxが9

に設定される前に、アレイ内の他の約束が解決しない前に、どこNum値9でありますあなたのループの内側だけplae x適切な出力を持っている:(私は疑問であることを述べた)

// create an array of promises to save some numbers 
for (let i = 0; i < 10; ++i) { 
    let x; 
    let p = new Promise((resolve,reject) => { 
    x = Num(); 
    x.num = i; 
    x.save((err) => { 
     if (err) { 
     reject(err); 
     } else { 
     resolve(x); 
     } 
    }); 
    }); 
    promises.push(p); 
}; 
+0

@ T.J.Crowder point taken。ありがとう! – Mike

+1

@ T.J.Crowderしました。 – Mike

関連する問題