How to yield multiple promises in for loop with vo.js? - javascript

Based on this example - vo/examples/9-pipeline-composition.js, how would I return yield a promise for each iteration of this for loop?
At the moment the loop runs once and yields a single promise.
function * get (urls) {
for (var i = urls.length - 1; i >= 0; i--) {
console.log(urls[i])
return yield http.get(urls[i])
}
}
function status (res, params) {
return res.status
}
let scrape = vo(get(['http://standupjack.com', 'https://google.com']), status)
vo([ scrape ])
.then(out => console.log('out', out))
.catch(e => console.error(e))

When u do the return inside the for loop, the loop breaks and returns the result and the loop wont move forward. You can call a function inside the for loop which handles the result and not return it.
function * get (urls) {
for (var i = urls.length - 1; i >= 0; i--) {
console.log(urls[i])
let result = yield http.get(urls[i])
yield handleResult(result)
}
}
Orelse u can push each of the results in an array and return all of then together at the end
function * get (urls) {
let resArr = []
for (var i = urls.length - 1; i >= 0; i--) {
console.log(urls[i])
let result = yield http.get(urls[i])
resArr.push(result)
}
return resArr
}

Related

Find all the Subarrays in O(nlog(n)) time complexity JavaScript

how to get all the subarrays in O(nlog(n)) time complexity using javaScript
I try with a nested loop but the time complexity is in O(n*n). I heard about some prefix solutions but have no information
try this code :
fetechArray = (array) => {
for ( let subarray of array ){
// ur code here
fetechArray(subarray);
}
}
Use the "divide & conquer" approach. You first divide the original array into two halves, then combine the results from both halves to get all subarrays.
function subArrays(arr) {
if (arr.length === 1) {
return [arr];
}
const mid = Math.floor(arr.length / 2);
const left = arr.slice(0, mid);
const right = arr.slice(mid);
const leftSubArrays = subArrays(left);
const rightSubArrays = subArrays(right);
return merge(leftSubArrays, rightSubArrays);
}
function merge(left, right) {
const result = [];
for (let i = 0; i < left.length; i++) {
for (let j = 0; j < right.length; j++) {
result.push(left[i].concat(right[j]));
}
}
return result;
}

Why does my function execute immediately even with setTimeout()? [duplicate]

This question already has answers here:
Why is the method executed immediately when I use setTimeout?
(8 answers)
Calling functions with setTimeout()
(6 answers)
Combination of async function + await + setTimeout
(17 answers)
Closed 7 months ago.
I have a program which is supposed to demonstrate a bubble sort, however I want the program to wait one second after every swap to demonstrate what swap is being made. Attached is my code:
function bubbleSort(arr){
for(var i = 0; i < arr.length-1; i++){
for(var j = 0; j < arr.length-i-1; j++){
if(arr[j] > arr[j+1]){
swap(arr,j,j+1);
}
}
}
}
Here is my swap function:
async function swap (arr,a,b){
var temp = arr[a];
var temp2 = arr;
temp2[a] = arr[b];
temp2[b] = temp;
await setTimeout(updateText(),1000);
return temp2;
}
And here is updateText:
function updateText(arrayText){
document.getElementById('arrayText').innerHTML = printArray(arr);
}
Whenever I execute the bubbleSort() function, my array goes from unsorted to sorted instantly, and does not show the swaps needed to reach the solved array.
updateText() is not called anywhere else in my program except for in the swap function.
Any help would be greatly appreciated and I can provide clarifications if needed.
The issue is the setTimeout function does not return a promise, which await expects.
function resolveAfter1Second() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved');
}, 1000);
});
}
async function swap (arr,a,b){
var temp = arr[a];
var temp2 = arr;
temp2[a] = arr[b];
temp2[b] = temp;
await resolveAfter1Second();
return temp2;
}
Here's an example that simply logs the array to the console. You can replace the console.log(arr) line with a web page update, as needed.
const waitFor = (delay) => new Promise((resolve) => setTimeout(resolve, delay));
async function bubbleSort(arr) {
for (let i = 0; i < arr.length - 1; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
await swap(arr, j, j + 1);
}
}
}
}
async function swap(arr, a, b) {
[arr[a], arr[b]] = [arr[b], arr[a]]
console.log(arr);
return waitFor(1000);
}
const array = [10, 9, 4, 5, 3, 1, 2];
bubbleSort(array);

Problems Implementing Multithreaded mergeSort in Javascript

I am new to coding for parallel processing and am attempting to implement a multithreaded Merge Sort algorithm. I am unclear on the proper usage of threads and how exactly it works, but I attempted to implement it anyway and this is where I landed. (tells me that slice is not a function)
function pMergeSort(input, done) {
const spawn = require('threads').spawn;
if (input.length< 2)
return input;
function partition(arr) {
let middle = Math.floor(arr.length / 2);
let left = arr.sclice(0, middle);
let right = arr.slice(middle + 1, arr.length);
}
let left,right=partition(input);
let task = spawn(pMergeSort).send(left).on('done', function (arr) {
if (result === undefined) {
for (let i = 0; i< n.length; i++) {
result[i] = n[i];
}
}else {
merge(result, n);
left.kill();
}
});
pMergeSort(right, function (n) {
if (result === undefined) {
for (let i = 0; i< n.length; i++) {
result[i] = n[i];
}
}else {
merge(result, n);
right.kill();
}
});
}
/*
function mergeSort (arr) {
if (arr.length === 1) {
// return once we hit an array with a single item
return arr
}
const middle = Math.floor(arr.length / 2) // get the middle item of the array rounded down
const left = arr.slice(0, middle) // items on the left side
const right = arr.slice(middle) // items on the right side
return merge(mergeSort(left), mergeSort(right))
}*/
// compare the arrays item by item and return the concatenated result
function merge(left, right) {
let result = []
let indexLeft = 0
let indexRight = 0
while (indexLeft < left.length && indexRight < right.length) {
if (left[indexLeft] < right[indexRight]) {
result.push(left[indexLeft])
indexLeft++
} else {
result.push(right[indexRight])
indexRight++
}
}
return result.concat(left.slice(indexLeft)).concat(right.slice(indexRight))
}
function genArray(size) {
// randomly fills arr
var arr = Array(size);
for (var i = 0; i < size; i++) {
arr[i] = Math.floor(Math.random() * 98);
}
return arr
}
function testParallel(){
var array=genArray(Math.floor(Math.random()*100));
pMergeSort(array, function(i){
console.log(JSON.stringify(i));
})
}
var testArr = genArray(2);
pMergeSort(testArr, function (i) {
console.log(JSON.stringify(i));
});
help implementing this would be amazing, but some simple questions that could push me in the right direction is, is the merge of pMergeSort supposed to be a callback function? how do you define your call back function? Would it be better to use a pool of threads rather than trying to spawn threads? And the function wrapped in pMergeSort should be merge sort + splitting into threads right?

How to iterate over a generator with indexes?

With arrays in javascript, getting the current index for iteration is easy. You can either use forEach and the index is the second entry, or use for...of and .entries() and array unpacking.
But generators have no .entries() method. How do I get the current index for a generator in my for...of loop?
I basically want:
function* myGen(){
let i = 0;
while(true) {
i+=1;
yield i;
}
}
for(let [j, index] of myGen().entries()) { //<-- I want .entries() but for a Generator
//...
}
//Running the above produces TypeError: myGen(...).entries(...) is not a function or its return value is not iterable
It is not advisable to add things to a built-in prototype, but if you really want your code to work like that (calling .entries() on any generator), then you could proceed as follows:
const Generator = Object.getPrototypeOf(function* () {});
Generator.prototype.entries = function * () {
let i = 0;
for (let value of this) {
yield [i++, value];
}
}
// Demo
function* myGen(){
let i = 64;
while(i < 70) {
i+=1;
yield String.fromCharCode(i);
}
}
for(let [j, index] of myGen().entries()) { //<-- Now you have .entries() on a Generator
console.log(j, index);
}
It is more prudent however to define a utility function.
const GeneratorUtils = {
* entriesOf(iter) {
let i = 0;
for (let value of iter) {
yield [i++, value];
}
}
};
// Demo
function* myGen(){
let i = 64;
while(i < 70) {
i+=1;
yield String.fromCharCode(i);
}
}
for(let [j, index] of GeneratorUtils.entriesOf(myGen())) {
console.log(j, index);
}
There's no built-in way to do it - the generator will have to yield something that contains the index. For example:
function* myGen(){
let index = 0;
while(index < 10) {
const item = 'foo' + index;
yield { item, index };
index++;
}
}
for(const { item, index } of myGen()) {
console.log('item: ' + item);
console.log('index: ' + index);
}
If you can't modify a generator that you want to also get the index of, you can put it inside another generator that does keep track of the index (or you could just increment on every iteration outside):
function* unmodifiableGen(){
// index is private, is not being yielded
let index = 0;
while(index < 10) {
yield Math.random();
index++;
}
}
function* generatorCounter(gen) {
// this index *will* be yielded:
let index = 0;
for (const item of gen()) {
yield { item, index };
index++;
}
}
for(const { item, index } of generatorCounter(unmodifiableGen)) {
console.log('item: ' + item);
console.log('index: ' + index);
}
But generators have no .entries() method. How do I get the current
index for a generator in my for...of loop?
You can utilize spread element preceding generator function call within an array literal and .entries() method of Array.prototype
function* myGen() {
let i = 0;
while (i < 10) {
i += 1;
yield i;
}
}
for (const [index, value] of [...myGen()].entries()) {
console.log(index, value);
}
A slightly different approach might be to make myGen() a regular function that returns an object adhering to the iterator protocol rather than a generator. Then you can just give it an entries() method. It will work a little differently than a generator (you can't call next() on it directly). But it be self-contained and should work as expected in situations where an iterator is expected:
function myGen(start, stop){
return {
[Symbol.iterator]: function* () {
while(start < stop){
yield start++
}
},
entries: function* entries (){
let i = 0
for (n of this){
yield [i++, n]
}
}
}
}
let g = myGen(10, 20)
// works like a regular iterator:
console.log([...g])
// but you can also call entries():
g = myGen(2, 9)
for ([i, n] of g.entries()){
console.log(`index: ${i}, value: ${n}`)
}

change the number of the iterator in a for loop

I want to conditionally break out of a loop like this..
for(let i = 0; i < 3; i++) {
exampleFunction().then(result => {
res = 0 ? i = 3 : null
})
}
I want exampleFunction to run at least 3 times unless it gets the desired result, in which case I want it to stop running.
exampleFunction runs asynchronously. The only way to get it working is using async/await.
const iterateWithExampleFunction = async () => {
for (let i = 0; i < 3; i++) {
console.log('before', i)
await exampleFunction().then(result => {
i = result === 0 ? 3: i;
});
console.log('after', i)
}
};
const exampleFunction = async () => {
return 0;
}
iterateWithExampleFunction();
You can have a count on the outer scope and then do the async call.
let count = 0;
function executeCall() {
exampleFunction().then(result => {
// do something with the result
if (result !== 0 && count !== 3) {
count += 1;
executeCall();
}
});
}
Just await the result, than break:
(async function() {
for(let i = 0; i < 3; i++) {
const result = await exampleFunction();
if(result === 0) break;
}
})();
Hopefully this gives you some ideas
async function poll(f, threshold = 3) {
if (!threshold) {
throw new Error("Value not found within configured amount of retries");
}
const result = await f();
if (result >= 0.5) {
return result;
} else {
return await poll(f, threshold - 1);
}
}
async function task() {
return Math.random();
}
poll(task).then(console.log).catch(console.error);

Categories